mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-10 20:00:27 +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; \
|
c; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define BUFFER_GROW 48
|
#define FP_BUFFER_GROW 48
|
||||||
#define BUFFER \
|
#define BUFFER \
|
||||||
({ \
|
({ \
|
||||||
int c = READ; \
|
int c = READ; \
|
||||||
if (bufcur >= bufsize - 1) { \
|
if (fpbufcur >= fpbufsize - 1) { \
|
||||||
bufsize = bufsize + BUFFER_GROW; \
|
fpbufsize = fpbufsize + FP_BUFFER_GROW; \
|
||||||
buf = realloc(buf, bufsize); \
|
fpbuf = realloc(fpbuf, fpbufsize); \
|
||||||
} \
|
} \
|
||||||
if (c != -1) { \
|
if (c != -1) { \
|
||||||
buf[bufcur++] = c; \
|
fpbuf[fpbufcur++] = c; \
|
||||||
buf[bufcur] = '\0'; \
|
fpbuf[fpbufcur] = '\0'; \
|
||||||
} \
|
} \
|
||||||
c; \
|
c; \
|
||||||
})
|
})
|
||||||
|
@ -76,9 +76,9 @@ int __vcscanf(int callback(void *), //
|
||||||
struct FreeMe *next;
|
struct FreeMe *next;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
} *freeme = NULL;
|
} *freeme = NULL;
|
||||||
unsigned char *buf = NULL;
|
unsigned char *fpbuf = NULL;
|
||||||
size_t bufsize;
|
size_t fpbufsize;
|
||||||
size_t bufcur;
|
size_t fpbufcur;
|
||||||
const unsigned char *p = (const unsigned char *)fmt;
|
const unsigned char *p = (const unsigned char *)fmt;
|
||||||
int *n_ptr;
|
int *n_ptr;
|
||||||
int items = 0;
|
int items = 0;
|
||||||
|
@ -103,6 +103,8 @@ int __vcscanf(int callback(void *), //
|
||||||
break;
|
break;
|
||||||
case '%': {
|
case '%': {
|
||||||
uint128_t number;
|
uint128_t number;
|
||||||
|
unsigned char *buf;
|
||||||
|
size_t bufsize;
|
||||||
double fp;
|
double fp;
|
||||||
unsigned width = 0;
|
unsigned width = 0;
|
||||||
unsigned char bits = 32;
|
unsigned char bits = 32;
|
||||||
|
@ -241,11 +243,11 @@ int __vcscanf(int callback(void *), //
|
||||||
while (isspace(c)) {
|
while (isspace(c)) {
|
||||||
c = READ;
|
c = READ;
|
||||||
}
|
}
|
||||||
bufsize = BUFFER_GROW;
|
fpbufsize = FP_BUFFER_GROW;
|
||||||
buf = malloc(bufsize);
|
fpbuf = malloc(fpbufsize);
|
||||||
bufcur = 0;
|
fpbufcur = 0;
|
||||||
buf[bufcur++] = c;
|
fpbuf[fpbufcur++] = c;
|
||||||
buf[bufcur] = '\0';
|
fpbuf[fpbufcur] = '\0';
|
||||||
goto ConsumeFloatingPointNumber;
|
goto ConsumeFloatingPointNumber;
|
||||||
default:
|
default:
|
||||||
items = einval();
|
items = einval();
|
||||||
|
@ -466,7 +468,7 @@ int __vcscanf(int callback(void *), //
|
||||||
break;
|
break;
|
||||||
} while ((c = BUFFER) != -1);
|
} while ((c = BUFFER) != -1);
|
||||||
GotFloatingPointNumber:
|
GotFloatingPointNumber:
|
||||||
fp = strtod((char *)buf, NULL);
|
fp = strtod((char *)fpbuf, NULL);
|
||||||
if (!discard) {
|
if (!discard) {
|
||||||
++items;
|
++items;
|
||||||
void *out = va_arg(va, void *);
|
void *out = va_arg(va, void *);
|
||||||
|
@ -476,9 +478,9 @@ int __vcscanf(int callback(void *), //
|
||||||
*(double *)out = (double)fp;
|
*(double *)out = (double)fp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(buf);
|
free(fpbuf);
|
||||||
buf = NULL;
|
fpbuf = NULL;
|
||||||
bufcur = bufsize = 0;
|
fpbufcur = fpbufsize = 0;
|
||||||
continue;
|
continue;
|
||||||
ReportConsumed:
|
ReportConsumed:
|
||||||
n_ptr = va_arg(va, int *);
|
n_ptr = va_arg(va, int *);
|
||||||
|
@ -565,6 +567,6 @@ Done:
|
||||||
if (items == -1) free(entry->ptr);
|
if (items == -1) free(entry->ptr);
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
if (buf) free(buf);
|
if (fpbuf) free(fpbuf);
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue