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:
------------------------------------------------------------------------------