mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-18 20:39:33 +08:00
* libc/stdio/vfprintf.c (_VFPRINTF_R): Don't truncate %p when
sizeof(void*) is 8 but sizeof(long) is 4. * libc/stdio/vfscanf.c (__SVFSCANF_R): Likewise. Fix %i scanning of "-0x". Support "-nan" and "inf" for %e. Audit usage of ungetc to fix reentrancy and bug on encoding error in multibyte locales. Always return EOF on read error.
This commit is contained in:
parent
443f9c5532
commit
aa5341f9ac
@ -1,3 +1,12 @@
|
||||
2007-05-23 Eric Blake <ebb9@byu.net>
|
||||
|
||||
* libc/stdio/vfprintf.c (_VFPRINTF_R): Don't truncate %p when
|
||||
sizeof(void*) is 8 but sizeof(long) is 4.
|
||||
* libc/stdio/vfscanf.c (__SVFSCANF_R): Likewise. Fix %i scanning
|
||||
of "-0x". Support "-nan" and "inf" for %e. Audit usage of ungetc
|
||||
to fix reentrancy and bug on encoding error in multibyte locales.
|
||||
Always return EOF on read error.
|
||||
|
||||
2007-05-23 Patrick Mansfield <patmans@us.ibm.com>
|
||||
|
||||
* libc/machine/spu/sys/syscall.h: Update the __send_to_ppe
|
||||
|
@ -1017,7 +1017,7 @@ reswitch: switch (ch) {
|
||||
* -- ANSI X3J11
|
||||
*/
|
||||
/* NOSTRICT */
|
||||
_uquad = (u_long)(unsigned _POINTER_INT)GET_ARG (N, ap, void_ptr_t);
|
||||
_uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
|
||||
base = HEX;
|
||||
xdigs = "0123456789abcdef";
|
||||
flags |= HEXPREFIX;
|
||||
|
@ -825,10 +825,10 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
*wcp = L'\0';
|
||||
if (mbslen != (size_t)-2) /* Incomplete sequence */
|
||||
{
|
||||
if (iswspace(*wcp))
|
||||
if (iswspace(*wcp))
|
||||
{
|
||||
while (n != 0)
|
||||
ungetc (buf[--n], fp);
|
||||
_ungetc_r (rptr, (unsigned char) buf[--n], fp);
|
||||
break;
|
||||
}
|
||||
nread += n;
|
||||
@ -987,15 +987,15 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
}
|
||||
break;
|
||||
|
||||
/* x ok iff flag still set & 2nd char */
|
||||
/* x ok iff flag still set & single 0 seen */
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (flags & PFXOK && p == buf + 1)
|
||||
if ((flags & (PFXOK | NZDIGITS)) == PFXOK)
|
||||
{
|
||||
base = 16;/* if %i */
|
||||
flags &= ~PFXOK;
|
||||
/* We must reset the NZDIGITS and NDIGITS
|
||||
flags that would have been unset by seeing
|
||||
flags that would have been unset by seeing
|
||||
the zero that preceded the X or x. */
|
||||
flags |= NZDIGITS | NDIGITS;
|
||||
goto ok;
|
||||
@ -1024,18 +1024,16 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
* If we had only a sign, it is no good; push back the sign.
|
||||
* If the number ends in `x', it was [sign] '0' 'x', so push back
|
||||
* the x and treat it as [sign] '0'.
|
||||
* Use of ungetc here and below assumes ASCII encoding; we are only
|
||||
* pushing back 7-bit characters, so casting to unsigned char is
|
||||
* not necessary.
|
||||
*/
|
||||
if (flags & NDIGITS)
|
||||
{
|
||||
if (p > buf)
|
||||
_CAST_VOID ungetc (*(u_char *)-- p, fp);
|
||||
goto match_failure;
|
||||
}
|
||||
c = ((u_char *) p)[-1];
|
||||
if (c == 'x' || c == 'X')
|
||||
{
|
||||
--p;
|
||||
/*(void)*/ ungetc (c, fp);
|
||||
_ungetc_r (rptr, *--p, fp); /* [-+xX] */
|
||||
if (p == buf)
|
||||
goto match_failure;
|
||||
}
|
||||
if ((flags & SUPPRESS) == 0)
|
||||
{
|
||||
@ -1044,7 +1042,19 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
*p = 0;
|
||||
res = (*ccfn) (rptr, buf, (char **) NULL, base);
|
||||
if (flags & POINTER)
|
||||
*(GET_ARG (N, ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res;
|
||||
{
|
||||
void **vp = GET_ARG (N, ap, void **);
|
||||
#ifndef _NO_LONGLONG
|
||||
if (sizeof (uintptr_t) > sizeof (u_long))
|
||||
{
|
||||
u_long_long resll;
|
||||
resll = _strtoull_r (rptr, buf, (char **) NULL, base);
|
||||
*vp = (void *) (uintptr_t) resll;
|
||||
}
|
||||
else
|
||||
#endif /* !_NO_LONGLONG */
|
||||
*vp = (void *) (uintptr_t) res;
|
||||
}
|
||||
#ifdef _WANT_IO_C99_FORMATS
|
||||
else if (flags & CHAR)
|
||||
{
|
||||
@ -1096,7 +1106,8 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
long zeroes, exp_adjust;
|
||||
char *exp_start = NULL;
|
||||
unsigned width_left = 0;
|
||||
int nancount = 0;
|
||||
char nancount = 0;
|
||||
char infcount = 0;
|
||||
#ifdef hardway
|
||||
if (width == 0 || width > sizeof (buf) - 1)
|
||||
#else
|
||||
@ -1141,7 +1152,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (nancount == 0)
|
||||
if (nancount + infcount == 0)
|
||||
{
|
||||
flags &= ~(SIGNOK | NDIGITS);
|
||||
goto fok;
|
||||
@ -1159,18 +1170,23 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
case 'n':
|
||||
case 'N':
|
||||
if (nancount == 0
|
||||
&& (flags & (SIGNOK | NDIGITS | DPTOK | EXPOK)) ==
|
||||
(SIGNOK | NDIGITS | DPTOK | EXPOK))
|
||||
&& (flags & (NDIGITS | DPTOK | EXPOK)) ==
|
||||
(NDIGITS | DPTOK | EXPOK))
|
||||
{
|
||||
flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
|
||||
nancount = 1;
|
||||
goto fok;
|
||||
}
|
||||
else if (nancount == 2)
|
||||
if (nancount == 2)
|
||||
{
|
||||
nancount = 3;
|
||||
goto fok;
|
||||
}
|
||||
if (infcount == 1 || infcount == 4)
|
||||
{
|
||||
infcount++;
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
@ -1180,6 +1196,46 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
if (infcount == 0
|
||||
&& (flags & (NDIGITS | DPTOK | EXPOK)) ==
|
||||
(NDIGITS | DPTOK | EXPOK))
|
||||
{
|
||||
flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
|
||||
infcount = 1;
|
||||
goto fok;
|
||||
}
|
||||
if (infcount == 3 || infcount == 5)
|
||||
{
|
||||
infcount++;
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
if (infcount == 2)
|
||||
{
|
||||
infcount = 3;
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
case 'T':
|
||||
if (infcount == 6)
|
||||
{
|
||||
infcount = 7;
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
case 'Y':
|
||||
if (infcount == 7)
|
||||
{
|
||||
infcount = 8;
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
case '.':
|
||||
if (flags & DPTOK)
|
||||
{
|
||||
@ -1212,7 +1268,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
*p++ = c;
|
||||
fskip:
|
||||
width--;
|
||||
++nread;
|
||||
++nread;
|
||||
if (--fp->_r > 0)
|
||||
fp->_p++;
|
||||
else
|
||||
@ -1221,24 +1277,48 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
}
|
||||
if (zeroes)
|
||||
flags &= ~NDIGITS;
|
||||
/* We may have a 'N' or possibly even a 'Na' as the start of 'NaN',
|
||||
only to run out of chars before it was complete (or having
|
||||
encountered a non- matching char). So check here if we have an
|
||||
outstanding nancount, and if so put back the chars we did
|
||||
swallow and treat as a failed match. */
|
||||
if (nancount && nancount != 3)
|
||||
{
|
||||
/* Ok... what are we supposed to do in the event that the
|
||||
__srefill call above was triggered in the middle of the partial
|
||||
'NaN' and so we can't put it all back? */
|
||||
while (nancount-- && (p > buf))
|
||||
{
|
||||
ungetc (*(u_char *)--p, fp);
|
||||
--nread;
|
||||
}
|
||||
goto match_failure;
|
||||
}
|
||||
/*
|
||||
/* We may have a 'N' or possibly even [sign] 'N' 'a' as the
|
||||
start of 'NaN', only to run out of chars before it was
|
||||
complete (or having encountered a non-matching char). So
|
||||
check here if we have an outstanding nancount, and if so
|
||||
put back the chars we did swallow and treat as a failed
|
||||
match.
|
||||
|
||||
FIXME - we still don't handle NAN([0xdigits]). */
|
||||
if (nancount - 1U < 2U) /* nancount && nancount < 3 */
|
||||
{
|
||||
/* Newlib's ungetc works even if we called __srefill in
|
||||
the middle of a partial parse, but POSIX does not
|
||||
guarantee that in all implementations of ungetc. */
|
||||
while (p > buf)
|
||||
{
|
||||
_ungetc_r (rptr, *--p, fp); /* [-+nNaA] */
|
||||
--nread;
|
||||
}
|
||||
goto match_failure;
|
||||
}
|
||||
/* Likewise for 'inf' and 'infinity'. But be careful that
|
||||
'infinite' consumes only 3 characters, leaving the stream
|
||||
at the second 'i'. */
|
||||
if (infcount - 1U < 7U) /* infcount && infcount < 8 */
|
||||
{
|
||||
if (infcount >= 3) /* valid 'inf', but short of 'infinity' */
|
||||
while (infcount-- > 3)
|
||||
{
|
||||
_ungetc_r (rptr, *--p, fp); /* [iInNtT] */
|
||||
--nread;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (p > buf)
|
||||
{
|
||||
_ungetc_r (rptr, *--p, fp); /* [-+iInN] */
|
||||
--nread;
|
||||
}
|
||||
goto match_failure;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If no digits, might be missing exponent digits
|
||||
* (just give back the exponent) or might be missing
|
||||
* regular digits, but had sign and/or decimal point.
|
||||
@ -1249,22 +1329,22 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
{
|
||||
/* no digits at all */
|
||||
while (p > buf)
|
||||
{
|
||||
ungetc (*(u_char *)--p, fp);
|
||||
--nread;
|
||||
}
|
||||
{
|
||||
_ungetc_r (rptr, *--p, fp); /* [-+.] */
|
||||
--nread;
|
||||
}
|
||||
goto match_failure;
|
||||
}
|
||||
/* just a bad exponent (e and maybe sign) */
|
||||
c = *(u_char *)-- p;
|
||||
--nread;
|
||||
c = *--p;
|
||||
--nread;
|
||||
if (c != 'e' && c != 'E')
|
||||
{
|
||||
_CAST_VOID ungetc (c, fp); /* sign */
|
||||
c = *(u_char *)-- p;
|
||||
--nread;
|
||||
_ungetc_r (rptr, c, fp); /* [-+] */
|
||||
c = *--p;
|
||||
--nread;
|
||||
}
|
||||
_CAST_VOID ungetc (c, fp);
|
||||
_ungetc_r (rptr, c, fp); /* [eE] */
|
||||
}
|
||||
if ((flags & SUPPRESS) == 0)
|
||||
{
|
||||
@ -1332,10 +1412,15 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||
}
|
||||
}
|
||||
input_failure:
|
||||
/* On read failure, return EOF failure regardless of matches; errno
|
||||
should have been set prior to here. On EOF failure (including
|
||||
invalid format string), return EOF if no matches yet, else number
|
||||
of matches made prior to failure. */
|
||||
_funlockfile (fp);
|
||||
return nassigned ? nassigned : -1;
|
||||
return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
|
||||
match_failure:
|
||||
all_done:
|
||||
/* Return number of matches, which can be 0 on match failure. */
|
||||
_funlockfile (fp);
|
||||
return nassigned;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user