mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-09 19:30:29 +00:00
vcscanf: refactor buffer usage
Create a dedicated buffer for floating point parsing purposes and restore the original string decoding buffer just as it was. This fixes the segmentation fault in the tinylinux mode tests. I suspect the floating point buffer was ending up in the free list somehow which resulted in a double free when the function exited.
This commit is contained in:
parent
8f12a061ad
commit
850ab95369
1 changed files with 21 additions and 19 deletions
|
@ -35,17 +35,17 @@
|
|||
c; \
|
||||
})
|
||||
|
||||
#define BUFFER_GROW 48
|
||||
#define FP_BUFFER_GROW 48
|
||||
#define BUFFER \
|
||||
({ \
|
||||
int c = READ; \
|
||||
if (bufcur >= bufsize - 1) { \
|
||||
bufsize = bufsize + BUFFER_GROW; \
|
||||
buf = realloc(buf, bufsize); \
|
||||
if (fpbufcur >= fpbufsize - 1) { \
|
||||
fpbufsize = fpbufsize + FP_BUFFER_GROW; \
|
||||
fpbuf = realloc(fpbuf, fpbufsize); \
|
||||
} \
|
||||
if (c != -1) { \
|
||||
buf[bufcur++] = c; \
|
||||
buf[bufcur] = '\0'; \
|
||||
fpbuf[fpbufcur++] = c; \
|
||||
fpbuf[fpbufcur] = '\0'; \
|
||||
} \
|
||||
c; \
|
||||
})
|
||||
|
@ -76,9 +76,9 @@ int __vcscanf(int callback(void *), //
|
|||
struct FreeMe *next;
|
||||
void *ptr;
|
||||
} *freeme = NULL;
|
||||
unsigned char *buf = NULL;
|
||||
size_t bufsize;
|
||||
size_t bufcur;
|
||||
unsigned char *fpbuf = NULL;
|
||||
size_t fpbufsize;
|
||||
size_t fpbufcur;
|
||||
const unsigned char *p = (const unsigned char *)fmt;
|
||||
int *n_ptr;
|
||||
int items = 0;
|
||||
|
@ -103,6 +103,8 @@ int __vcscanf(int callback(void *), //
|
|||
break;
|
||||
case '%': {
|
||||
uint128_t number;
|
||||
unsigned char *buf;
|
||||
size_t bufsize;
|
||||
double fp;
|
||||
unsigned width = 0;
|
||||
unsigned char bits = 32;
|
||||
|
@ -241,11 +243,11 @@ int __vcscanf(int callback(void *), //
|
|||
while (isspace(c)) {
|
||||
c = READ;
|
||||
}
|
||||
bufsize = BUFFER_GROW;
|
||||
buf = malloc(bufsize);
|
||||
bufcur = 0;
|
||||
buf[bufcur++] = c;
|
||||
buf[bufcur] = '\0';
|
||||
fpbufsize = FP_BUFFER_GROW;
|
||||
fpbuf = malloc(fpbufsize);
|
||||
fpbufcur = 0;
|
||||
fpbuf[fpbufcur++] = c;
|
||||
fpbuf[fpbufcur] = '\0';
|
||||
goto ConsumeFloatingPointNumber;
|
||||
default:
|
||||
items = einval();
|
||||
|
@ -466,7 +468,7 @@ int __vcscanf(int callback(void *), //
|
|||
break;
|
||||
} while ((c = BUFFER) != -1);
|
||||
GotFloatingPointNumber:
|
||||
fp = strtod((char *)buf, NULL);
|
||||
fp = strtod((char *)fpbuf, NULL);
|
||||
if (!discard) {
|
||||
++items;
|
||||
void *out = va_arg(va, void *);
|
||||
|
@ -476,9 +478,9 @@ int __vcscanf(int callback(void *), //
|
|||
*(double *)out = (double)fp;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
bufcur = bufsize = 0;
|
||||
free(fpbuf);
|
||||
fpbuf = NULL;
|
||||
fpbufcur = fpbufsize = 0;
|
||||
continue;
|
||||
ReportConsumed:
|
||||
n_ptr = va_arg(va, int *);
|
||||
|
@ -565,6 +567,6 @@ Done:
|
|||
if (items == -1) free(entry->ptr);
|
||||
free(entry);
|
||||
}
|
||||
if (buf) free(buf);
|
||||
if (fpbuf) free(fpbuf);
|
||||
return items;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue