stdio: fix scanf bounds breaking strto*

Mostly an initialization problem. But I also optimized the check by
making the bound a maximal unsigned integer when there is no bound,
since __scanf_peek() is used a lot.
This commit is contained in:
Lephenixnoir 2024-01-14 15:25:55 +01:00
parent d8a55b728d
commit c776336a0d
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
9 changed files with 29 additions and 25 deletions

View File

@ -6,12 +6,11 @@
void __scanf_start(struct __scanf_input *in)
{
if(in->fp)
in->buffer = fgetc(in->fp);
else {
in->buffer = (*in->str ? *in->str : EOF);
in->str += (in->buffer != 0);
in->str += (in->buffer != EOF);
}
}
@ -286,7 +285,7 @@ int __scanf(
// we need to assign the read char to the corresponding pointer
if (!skip) {
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==-1) {
if (in->readmaxlength==(unsigned int)-1) {
for(;;) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
@ -305,7 +304,7 @@ int __scanf(
}
}
else {
for(int u=0; u<in->readmaxlength; u++) {
for(unsigned int u=0; u<in->readmaxlength; u++) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else if (__is_allowed( temp )) {
@ -332,7 +331,7 @@ int __scanf(
else
{
if (in->readmaxlength==-1) {
if (in->readmaxlength==(unsigned int)-1) {
for(;;) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
@ -345,7 +344,7 @@ int __scanf(
}
}
else {
for(int u=0; u<in->readmaxlength; u++) {
for(unsigned int u=0; u<in->readmaxlength; u++) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else if (__is_allowed( temp )) __scanf_in( in );
@ -546,13 +545,13 @@ int __scanf(
char temp;
if (!skip) {
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==-1) {
if (in->readmaxlength==(unsigned int)-1) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else *c = __scanf_in( in );
}
else {
for( int u = 0; u < in->readmaxlength; u++ ) {
for( unsigned int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else *c++ = __scanf_in( in );
@ -560,7 +559,7 @@ int __scanf(
}
}
else {
if (in->readmaxlength==-1) {
if (in->readmaxlength==(unsigned int)-1) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else {
@ -569,7 +568,7 @@ int __scanf(
}
}
else {
for( int u = 0; u < in->readmaxlength; u++ ) {
for( unsigned int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else __scanf_in( in );
@ -590,7 +589,7 @@ int __scanf(
__purge_space( in );
if (!skip) {
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==-1) {
if (in->readmaxlength==(unsigned int)-1) {
loopstring:
temp = __scanf_peek( in );
if (temp==EOF && curstrlength==0) return validrets;
@ -605,7 +604,7 @@ int __scanf(
}
}
else {
for( int u = 0; u < in->readmaxlength; u++ ) {
for( unsigned int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF && curstrlength==0) return validrets;
if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) {
@ -620,7 +619,7 @@ int __scanf(
}
}
else {
if (in->readmaxlength==-1) {
if (in->readmaxlength==(unsigned int)-1) {
loopstringskip:
temp = __scanf_peek( in );
if (temp==EOF && curstrlength==0) return validrets;
@ -632,7 +631,7 @@ int __scanf(
}
}
else {
for( int u = 0; u < in->readmaxlength; u++ ) {
for( unsigned int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF && curstrlength==0) return validrets;
if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) goto loopstringendskip;

View File

@ -19,7 +19,7 @@ struct __scanf_input {
FILE *fp;
// max char to read from the input stream as per user length modifier
int readmaxlength;
unsigned int readmaxlength;
int currentlength;
// total number of char read so far in the current call of a XYscanf() function (to return a %n when required)
@ -55,9 +55,8 @@ static inline int __scanf_in(struct __scanf_input *__in)
/* Peek the next byte without advancing. */
static inline int __scanf_peek(struct __scanf_input *__in)
{
if (__in->readmaxlength==-1 || __in->currentlength<__in->readmaxlength )
return __in->buffer;
else return 0;
return ((unsigned)__in->currentlength < __in->readmaxlength)
? __in->buffer : EOF;
}
/* Close the input by unsending the buffer once finished. */

View File

@ -7,7 +7,7 @@ double strtod(char const * restrict ptr, char ** restrict endptr)
if(endptr)
*endptr = (char *)ptr;
struct __scanf_input in = { .str = ptr, .fp = NULL };
struct __scanf_input in = { .str = ptr, .fp = NULL, .readmaxlength = -1 };
__scanf_start(&in);
int err = __strto_fp(&in, &d, NULL, NULL);
__scanf_end(&in);

View File

@ -7,7 +7,7 @@ float strtof(char const * restrict ptr, char ** restrict endptr)
if(endptr)
*endptr = (char *)ptr;
struct __scanf_input in = { .str = ptr, .fp = NULL };
struct __scanf_input in = { .str = ptr, .fp = NULL, .readmaxlength = -1 };
__scanf_start(&in);
int err = __strto_fp(&in, NULL, &f, NULL);
__scanf_end(&in);

View File

@ -7,7 +7,13 @@ long int strtol(char const * restrict ptr, char ** restrict endptr, int base)
if(endptr)
*endptr = (char *)ptr;
struct __scanf_input in = { .str = ptr, .fp = NULL };
struct __scanf_input in = {
.str = ptr,
.fp = NULL,
.readmaxlength = -1,
.currentlength = 0,
.readsofar = 0,
};
__scanf_start(&in);
int err = __strto_int(&in, base, &n, NULL, false);
__scanf_end(&in);

View File

@ -7,7 +7,7 @@ long double strtold(char const * restrict ptr, char ** restrict endptr)
if(endptr)
*endptr = (char *)ptr;
struct __scanf_input in = { .str = ptr, .fp = NULL };
struct __scanf_input in = { .str = ptr, .fp = NULL, .readmaxlength = -1 };
__scanf_start(&in);
int err = __strto_fp(&in, NULL, NULL, &ld);
__scanf_end(&in);

View File

@ -8,7 +8,7 @@ long long int strtoll(char const * restrict ptr, char ** restrict endptr,
if(endptr)
*endptr = (char *)ptr;
struct __scanf_input in = { .str = ptr, .fp = NULL };
struct __scanf_input in = { .str = ptr, .fp = NULL, .readmaxlength = -1 };
__scanf_start(&in);
int err = __strto_int(&in, base, NULL, &n, false);
__scanf_end(&in);

View File

@ -8,7 +8,7 @@ unsigned long int strtoul(char const * restrict ptr, char ** restrict endptr,
if(endptr)
*endptr = (char *)ptr;
struct __scanf_input in = { .str = ptr, .fp = NULL };
struct __scanf_input in = { .str = ptr, .fp = NULL, .readmaxlength = -1 };
__scanf_start(&in);
int err = __strto_int(&in, base, (long *)&n, NULL, true);
__scanf_end(&in);

View File

@ -8,7 +8,7 @@ unsigned long long int strtoull(char const * restrict ptr,
if(endptr)
*endptr = (char *)ptr;
struct __scanf_input in = { .str = ptr, .fp = NULL };
struct __scanf_input in = { .str = ptr, .fp = NULL, .readmaxlength = -1 };
__scanf_start(&in);
int err = __strto_int(&in, base, NULL, (long long *)&n, true);
__scanf_end(&in);