| Summary: | sscanf() fails on 64-bit operations | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Jin Guojun <jin> |
| Component: | misc | Assignee: | Bill Fenner <fenner> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | Unspecified | ||
| Hardware: | Any | ||
| OS: | Any | ||
On Mon, 17 Jul 2000, Jin Guojun wrote:
> >How-To-Repeat:
>
> main(argc, argv)
> {
> int rev, i = 1;
> if (!strcmp(argv[i], "-r")) {
> rev = 1;
> i++;
> } else rev = 0;
> {
> int64_t h;
> rev ? sscanf(argv[i], "%lld", &h) : sscanf(argv[i], "%llx", &h);
> printf(rev ? "0x%016llX\n": "%lld\n", h);
> }
> }
64-bit types are unportable. FreeBSD's scanf only supports reading "quad"
types using %qd format.
FreeBSD's scanf also has some overflow handling bugs from misusing strtoq
to handle non-quads.
Bruce
Bruce
On Mon, 17 Jul 2000, Bruce Evans <bde@zeta.org.au> wrote: > > >How-To-Repeat: > > > > main(argc, argv) > > { > > int rev, i = 1; > > if (!strcmp(argv[i], "-r")) { > > rev = 1; > > i++; > > } else rev = 0; > > { > > int64_t h; > > rev ? sscanf(argv[i], "%lld", &h) : sscanf(argv[i], "%llx", &h > ); > > printf(rev ? "0x%016llX\n": "%lld\n", h); > > } > > } > > 64-bit types are unportable. FreeBSD's scanf only supports reading "quad" > types using %qd format. > > FreeBSD's scanf also has some overflow handling bugs from misusing strtoq > to handle non-quads. Shall we have "%lld" in FreeBSD to make it portable with other systems? -Jin Hi, I really think we should support %lld with *scanf. After all, we support it with *printf. It bit me when trying to compile the latest ORBit (0.5.7). Here's a patch that does the trick. Bye, Rolf Index: stdio/vfscanf.c =================================================================== RCS file: /home/ncvs/src/lib/libc/stdio/vfscanf.c,v retrieving revision 1.14 diff -c -r1.14 vfscanf.c *** stdio/vfscanf.c 1999/08/28 00:01:20 1.14 --- stdio/vfscanf.c 2001/02/18 18:03:04 *************** *** 165,171 **** flags |= SUPPRESS; goto again; case 'l': ! flags |= LONG; goto again; case 'q': flags |= QUAD; --- 165,174 ---- flags |= SUPPRESS; goto again; case 'l': ! if (flags & LONG) ! flags |= QUAD; ! else ! flags |= LONG; goto again; case 'q': flags |= QUAD; *************** *** 265,276 **** nconversions++; if (flags & SUPPRESS) /* ??? */ continue; ! if (flags & SHORT) ! *va_arg(ap, short *) = nread; else if (flags & LONG) *va_arg(ap, long *) = nread; ! else if (flags & QUAD) ! *va_arg(ap, quad_t *) = nread; else *va_arg(ap, int *) = nread; continue; --- 268,279 ---- nconversions++; if (flags & SUPPRESS) /* ??? */ continue; ! if (flags & QUAD) ! *va_arg(ap, quad_t *) = nread; else if (flags & LONG) *va_arg(ap, long *) = nread; ! else if (flags & SHORT) ! *va_arg(ap, short *) = nread; else *va_arg(ap, int *) = nread; continue; *************** *** 555,566 **** if (flags & POINTER) *va_arg(ap, void **) = (void *)(u_long)res; - else if (flags & SHORT) - *va_arg(ap, short *) = res; - else if (flags & LONG) - *va_arg(ap, long *) = res; else if (flags & QUAD) *va_arg(ap, quad_t *) = res; else *va_arg(ap, int *) = res; nassigned++; --- 558,569 ---- if (flags & POINTER) *va_arg(ap, void **) = (void *)(u_long)res; else if (flags & QUAD) *va_arg(ap, quad_t *) = res; + else if (flags & LONG) + *va_arg(ap, long *) = res; + else if (flags & SHORT) + *va_arg(ap, short *) = res; else *va_arg(ap, int *) = res; nassigned++; Responsible Changed From-To: freebsd-bugs->roam It's rumored that Peter has been thinking about fixing this Responsible Changed From-To: roam->fenner I'm working on c99 support for scanf, which includes %lld. State Changed From-To: open->patched I added c99 %lld support in rev 1.22 of vfscanf.c State Changed From-To: patched->closed Committed back in 2002. |
sscanf(), and maybe scanf ..., fails on 64-bit operation. On Solaris, IRIX and Linux systems, the code below outputs: % hextodec -r 963870220966261 0x00036CA286215975 % hextodec 0x00036CA286215975 963870220966261 % hextodec 0x2804C6B886215975 2883648157250574709 Under FreeBSD % hextodec -r 963870220966261 0x2804C6B886215975 % hextodec 0x00036CA286215975 2883648157250574709 % hextodec 0x2804C6B886215975 # this seems correct 2883648157250574709 How-To-Repeat: main(argc, argv) { int rev, i = 1; if (!strcmp(argv[i], "-r")) { rev = 1; i++; } else rev = 0; { int64_t h; rev ? sscanf(argv[i], "%lld", &h) : sscanf(argv[i], "%llx", &h); printf(rev ? "0x%016llX\n": "%lld\n", h); } }