Subject: bin/144: primes doesn't like big numbers
To: None <gnats-admin>
From: Arne Juul <arnej@dsl.unit.no>
List: netbsd-bugs
Date: 02/28/1994 15:50:01
>Number:         144
>Category:       bin
>Synopsis:       /usr/games/primes fails for large numbers
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    gnats-admin (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 28 15:50:01 1994
>Originator:     Arne Juul
>Organization:
University of Trondheim, Norway
>Release:        0.9-current
>Environment:
	Current files sup'ed  Feb 27.
System: NetBSD skarven.dsl.unit.no 0.9a SKARVEN#0 i386

>Description:
	Contrary to what is claimed in the man-page, primes did
	not support numbers in the 2^31 - 2^32 range. According
	to comments in the code, this was because of problems with
	double<->long conversion in some environments (presumably
	not in NetBSD). Redefining the upper bound for input
	and using %lu format conversions throughout solved the problem.
	(Nicer error outputs would also be nice, but I did not
	really fix).
>How-To-Repeat:
	/usr/games/primes 3000000000
>Fix:
	Apply this fix in /usr/src/games/primes:

*** primes.c.orig	Fri Dec 17 06:53:47 1993
--- primes.c	Sun Feb 27 12:15:52 1994
***************
*** 68,73 ****
--- 68,74 ----
  #include <math.h>
  #include <memory.h>
  #include <ctype.h>
+ #include <limits.h>
  #include "primes.h"
  
  /*
***************
*** 129,139 ****
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
! 		if (sscanf(argv[1], "%ld", &start) != 1) {
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
! 		if (sscanf(argv[2], "%ld", &stop) != 1) {
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
--- 130,140 ----
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
! 		if (sscanf(argv[1], "%lu", &start) != 1) {
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
! 		if (sscanf(argv[2], "%lu", &stop) != 1) {
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
***************
*** 144,150 ****
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
! 		if (sscanf(argv[1], "%ld", &start) != 1) {
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
--- 145,151 ----
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
! 		if (sscanf(argv[1], "%lu", &start) != 1) {
  			fprintf(stderr, "%s: ouch\n", program);
  			exit(1);
  		}
***************
*** 154,160 ****
  		if (read_num_buf(stdin, buf) != NULL) {
  
  			/* convert the buffer */
! 			if (sscanf(buf, "%ld", &start) != 1) {
  				fprintf(stderr, "%s: ouch\n", program);
  				exit(1);
  			}
--- 155,161 ----
  		if (read_num_buf(stdin, buf) != NULL) {
  
  			/* convert the buffer */
! 			if (sscanf(buf, "%lu", &start) != 1) {
  				fprintf(stderr, "%s: ouch\n", program);
  				exit(1);
  			}
***************
*** 210,218 ****
  	char *p;	/* scan pointer */
  	char *z;	/* zero scan pointer */
  
! 	/* form the ascii value of SEMIBIG if needed */
  	if (!isascii(limit[0]) || !isdigit(limit[0])) {
! 		sprintf(limit, "%ld", SEMIBIG);
  		limit_len = strlen(limit);
  	}
  	
--- 211,219 ----
  	char *p;	/* scan pointer */
  	char *z;	/* zero scan pointer */
  
! 	/* form the ascii value of BIG if needed */
  	if (!isascii(limit[0]) || !isdigit(limit[0])) {
! 		sprintf(limit, "%lu", BIG);
  		limit_len = strlen(limit);
  	}
  	
***************
*** 234,240 ****
  
  		/* object if - */
  		if (*s == '-') {
! 			fprintf(stderr, "%s: ouch\n", program);
  			continue;
  		}
  
--- 235,241 ----
  
  		/* object if - */
  		if (*s == '-') {
! 			fprintf(stderr, "%s: ouch for minuses\n", program);
  			continue;
  		}
  
***************
*** 275,286 ****
  
  		/* reject very large numbers */
  		} else if (len > limit_len) {
! 			fprintf(stderr, "%s: ouch\n", program);
  			continue;
  
  		/* carefully check against near limit numbers */
  		} else if (strcmp(z, limit) > 0) {
! 			fprintf(stderr, "%s: ouch\n", program);
  			continue;
  		}
  		/* number is near limit, but is under it */
--- 276,287 ----
  
  		/* reject very large numbers */
  		} else if (len > limit_len) {
! 			fprintf(stderr, "%s: %s too big\n", program, z);
  			continue;
  
  		/* carefully check against near limit numbers */
  		} else if (strcmp(z, limit) > 0) {
! 			fprintf(stderr, "%s: %s a bit too big\n", program, z);
  			continue;
  		}
  		/* number is near limit, but is under it */
***************
*** 306,315 ****
  	register ubig fact_lim;		/* highest prime for current block */
  
  	/*
! 	 * A number of systems can not convert double values 
! 	 * into unsigned longs when the values are larger than
! 	 * the largest signed value.  Thus we take case when
! 	 * the double is larger than the value SEMIBIG. *sigh*
  	 */
  	if (start < 3) {
  		start = (ubig)2;
--- 307,315 ----
  	register ubig fact_lim;		/* highest prime for current block */
  
  	/*
! 	 * NetBSD has no problems with handling conversion
! 	 * between doubles and unsigned long, so we can go
! 	 * all the way to BIG.
  	 */
  	if (start < 3) {
  		start = (ubig)2;
*** primes.h.orig	Fri Dec 17 06:53:47 1993
--- primes.h	Sun Feb 27 12:14:12 1994
***************
*** 51,57 ****
  /*
   * sieve parameters
   */
! #define BIG ((ubig)0xffffffff)        /* highest value we will sieve */
! #define SEMIBIG ((ubig)0x7fffffff)    /* highest signed value */
! #define NEG_SEMIBIG ((ubig)0x80000000) /* lowest signed value */
! #define TABSIZE 256*1024 /* bytes in sieve table (must be > 3*5*7*11) */
--- 51,57 ----
  /*
   * sieve parameters
   */
! #define BIG		ULONG_MAX      		/* highest value we will sieve */
! #define SEMIBIG		((ubig)LONG_MAX)	/* highest signed value */
! #define NEG_SEMIBIG	((ubig)LONG_MIN)	/* lowest signed value */
! #define TABSIZE 256*1024			/* bytes in sieve table (must be > 3*5*7*11) */
>Audit-Trail:
>Unformatted:


------------------------------------------------------------------------------