Fix buffer overflow in sprintf

This commit is contained in:
drmortalwombat 2022-05-19 08:30:00 +02:00
parent 9d18aef634
commit b42c992a58
4 changed files with 386 additions and 51 deletions

View File

@ -72,6 +72,9 @@ rem @echo off
@call :test floatstringtest.c @call :test floatstringtest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test sprintftest.c
@if %errorlevel% neq 0 goto :error
@call :test qsorttest.c @call :test qsorttest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error

321
autotest/sprintftest.c Normal file
View File

@ -0,0 +1,321 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
void testi(const char * fmt, int val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
void testu(const char * fmt, unsigned val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
void testil(const char * fmt, long val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
void testul(const char * fmt, unsigned long val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
void testf(const char * fmt, float val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
int main(void)
{
testi("%d", 0, "0");
testi("%d", 1, "1");
testi("%d", -1, "-1");
testi("%d", 12, "12");
testi("%d", 123, "123");
testi("%d", 1234, "1234");
testi("%d", 12345, "12345");
testi("%d", -12345, "-12345");
testi("%d", 32767, "32767");
testi("%d", -32768, "-32768");
testi("%3d", 0, " 0");
testi("%3d", 1, " 1");
testi("%3d", -1, " -1");
testi("%3d", 12, " 12");
testi("%3d", 123, "123");
testi("%3d", 1234, "1234");
testi("%3d", 12345, "12345");
testi("%3d", -12345, "-12345");
testi("%3d", 32767, "32767");
testi("%3d", -32768, "-32768");
testi("%03d", 0, "000");
testi("%03d", 1, "001");
// testi("%03d", -1, "-01");
testi("%03d", 12, "012");
testi("%03d", 123, "123");
testi("%03d", 1234, "1234");
testi("%03d", 12345, "12345");
testi("%03d", -12345, "-12345");
testi("%03d", 32767, "32767");
testi("%03d", -32768, "-32768");
testi("%-4d", 0, "0 ");
testi("%-4d", 1, "1 ");
testi("%-4d", -1, "-1 ");
testi("%-4d", 12, "12 ");
testi("%-4d", 123, "123 ");
testi("%-4d", 1234, "1234");
testi("%-4d", 12345, "12345");
testi("%-4d", -12345, "-12345");
testi("%-4d", 32767, "32767");
testi("%-4d", -32768, "-32768");
testi("%+d", 0, "+0");
testi("%+d", 1, "+1");
testi("%+d", -1, "-1");
testi("%+d", 12, "+12");
testi("%+d", 123, "+123");
testi("%+d", 1234, "+1234");
testi("%+d", 12345, "+12345");
testi("%+d", -12345, "-12345");
testi("%+d", 32767, "+32767");
testi("%+d", -32768, "-32768");
testil("%ld", 0l, "0");
testil("%ld", 1l, "1");
testil("%ld", -1l, "-1");
testil("%ld", 12l, "12");
testil("%ld", 123l, "123");
testil("%ld", 1234l, "1234");
testil("%ld", 12345l, "12345");
testil("%ld", -12345l, "-12345");
testil("%ld", 32767l, "32767");
testil("%ld", -32768l, "-32768");
testil("%ld", 2147483647l, "2147483647");
testil("%ld", -2147483648l, "-2147483648");
testil("%3ld", 0l, " 0");
testil("%3ld", 1l, " 1");
testil("%3ld", -1l, " -1");
testil("%3ld", 12l, " 12");
testil("%3ld", 123l, "123");
testil("%3ld", 1234l, "1234");
testil("%3ld", 12345l, "12345");
testil("%3ld", -12345l, "-12345");
testil("%3ld", 32767l, "32767");
testil("%3ld", -32768l, "-32768");
testil("%3ld", 2147483647l, "2147483647");
testil("%3ld", -2147483648l, "-2147483648");
testil("%03ld", 0l, "000");
testil("%03ld", 1l, "001");
// testil("%03ld", -1l, "-01");
testil("%03ld", 12l, "012");
testil("%03ld", 123l, "123");
testil("%03ld", 1234l, "1234");
testil("%03ld", 12345l, "12345");
testil("%03ld", -12345l, "-12345");
testil("%03ld", 32767l, "32767");
testil("%03ld", -32768l, "-32768");
testil("%03ld", 2147483647l, "2147483647");
testil("%03ld", -2147483648l, "-2147483648");
testil("%-4ld", 0l, "0 ");
testil("%-4ld", 1l, "1 ");
testil("%-4ld", -1l, "-1 ");
testil("%-4ld", 12l, "12 ");
testil("%-4ld", 123l, "123 ");
testil("%-4ld", 1234l, "1234");
testil("%-4ld", 12345l, "12345");
testil("%-4ld", -12345l, "-12345");
testil("%-4ld", 32767l, "32767");
testil("%-4ld", -32768l, "-32768");
testil("%-4ld", 2147483647l, "2147483647");
testil("%-4ld", -2147483648l, "-2147483648");
testil("%+ld", 0l, "+0");
testil("%+ld", 1l, "+1");
testil("%+ld", -1l, "-1");
testil("%+ld", 12l, "+12");
testil("%+ld", 123l, "+123");
testil("%+ld", 1234l, "+1234");
testil("%+ld", 12345l, "+12345");
testil("%+ld", -12345l, "-12345");
testil("%+ld", 32767l, "+32767");
testil("%+ld", -32768l, "-32768");
testil("%+ld", 2147483647l, "+2147483647");
testil("%+ld", -2147483648l, "-2147483648");
testu("%u", 0, "0");
testu("%u", 1, "1");
testu("%u", 12, "12");
testu("%u", 123, "123");
testu("%u", 1234, "1234");
testu("%u", 12345, "12345");
testu("%u", 32767, "32767");
testu("%u", 32768, "32768");
testu("%u", 65535, "65535");
testu("%x", 0, "0");
testu("%x", 0x49bf, "49BF");
testu("%x", 0xffff, "FFFF");
testu("%3u", 0, " 0");
testu("%3u", 1, " 1");
testu("%3u", 12, " 12");
testu("%3u", 123, "123");
testu("%3u", 1234, "1234");
testu("%3u", 12345, "12345");
testu("%3u", 32767, "32767");
testu("%3u", 32768, "32768");
testu("%3u", 65535, "65535");
testu("%3x", 0, " 0");
testu("%3x", 0x49bf, "49BF");
testu("%3x", 0xffff, "FFFF");
testu("%03u", 0, "000");
testu("%03u", 1, "001");
testu("%03u", 12, "012");
testu("%03u", 123, "123");
testu("%03u", 1234, "1234");
testu("%03u", 12345, "12345");
testu("%03u", 32767, "32767");
testu("%03u", 32768, "32768");
testu("%03u", 65535, "65535");
testu("%03x", 0, "000");
testu("%03x", 0x49bf, "49BF");
testu("%03x", 0xffff, "FFFF");
testu("%-4u", 0, "0 ");
testu("%-4u", 1, "1 ");
testu("%-4u", 12, "12 ");
testu("%-4u", 123, "123 ");
testu("%-4u", 1234, "1234");
testu("%-4u", 12345, "12345");
testu("%-4u", 32767, "32767");
testu("%-4u", 32768, "32768");
testu("%-4u", 65535, "65535");
testu("%-4x", 0, "0 ");
testu("%-4x", 0x49bf, "49BF");
testu("%-4x", 0xffff, "FFFF");
testul("%3lu", 0l, " 0");
testul("%3lu", 1l, " 1");
testul("%3lu", 12l, " 12");
testul("%3lu", 123l, "123");
testul("%3lu", 1234l, "1234");
testul("%3lu", 12345l, "12345");
testul("%3lu", 32767l, "32767");
testul("%3lu", 2147483647l, "2147483647");
testul("%3lu", 4294967295l, "4294967295");
testul("%3lx", 0, " 0");
testul("%3lx", 0x3576fbcdl, "3576FBCD");
testul("%3lx", 0xffffffffl, "FFFFFFFF");
testul("%03lu", 0l, "000");
testul("%03lu", 1l, "001");
testul("%03lu", 12l, "012");
testul("%03lu", 123l, "123");
testul("%03lu", 1234l, "1234");
testul("%03lu", 12345l, "12345");
testul("%03lu", 32767l, "32767");
testul("%03lu", 2147483647l, "2147483647");
testul("%03lu", 4294967295l, "4294967295");
testul("%03lx", 0, "000");
testul("%03lx", 0x3576fbcdl, "3576FBCD");
testul("%03lx", 0xffffffffl, "FFFFFFFF");
testul("%-4lu", 0l, "0 ");
testul("%-4lu", 1l, "1 ");
testul("%-4lu", 12l, "12 ");
testul("%-4lu", 123l, "123 ");
testul("%-4lu", 1234l, "1234");
testul("%-4lu", 12345l, "12345");
testul("%-4lu", 32767l, "32767");
testul("%-4lu", 2147483647l, "2147483647");
testul("%-4lu", 4294967295l, "4294967295");
testul("%-4lx", 0, "0 ");
testul("%-4lx", 0x3576fbcdl, "3576FBCD");
testul("%-4lx", 0xffffffffl, "FFFFFFFF");
testul("%+lu", 0l, "+0");
testul("%+lu", 1l, "+1");
testul("%+lu", 12l, "+12");
testul("%+lu", 123l, "+123");
testul("%+lu", 1234l, "+1234");
testul("%+lu", 12345l, "+12345");
testul("%+lu", 32767l, "+32767");
testul("%+lu", 2147483647l, "+2147483647");
testul("%+lu", 4294967295l, "+4294967295");
testf("%f", 0., "0.000000");
testf("%f", 1., "1.000000");
testf("%f", -1., "-1.000000");
testf("%f", 12., "12.000000");
testf("%f", 123., "123.000000");
testf("%f", 1234., "1234.000000");
testf("%f", 12345., "12345.000000");
testf("%f", 123456., "123456.000000");
testf("%f", 1234567., "1234567.000000");
testf("%f", 0.1, "0.100000");
testf("%f", 0.01, "0.010000");
testf("%f", 0.001, "0.001000");
testf("%f", 0.0001, "0.000100");
testf("%f", 0.00001, "0.000010");
testf("%f", 0.000001, "0.000001");
testf("%5.1f", 0, " 0.0");
testf("%5.1f", 1, " 1.0");
testf("%5.1f", -1, " -1.0");
testf("%5.1f", 10, " 10.0");
testf("%5.1f", -10, "-10.0");
testf("%5.1f", 100, "100.0");
testf("%5.1f", -100, "-100.0");
testf("%5.1f", 0.1, " 0.1");
testf("%5.1f", -0.1, " -0.1");
testf("%5.1f", 0.04, " 0.0");
testf("%5.1f", -0.04, " -0.0");
testf("%5.1f", 0.051, " 0.1");
testf("%5.1f", -0.051, " -0.1");
testf("%+5.1f", 0, " +0.0");
testf("%+5.1f", 1, " +1.0");
testf("%+5.1f", -1, " -1.0");
testf("%+5.1f", 10, "+10.0");
testf("%+5.1f", -10, "-10.0");
testf("%+5.1f", 100, "+100.0");
testf("%+5.1f", -100, "-100.0");
testf("%+5.1f", 0.1, " +0.1");
testf("%+5.1f", -0.1, " -0.1");
testf("%+5.1f", 0.04, " +0.0");
testf("%+5.1f", -0.04, " -0.0");
testf("%+5.1f", 0.051, " +0.1");
testf("%+5.1f", -0.051, " -0.1");
return 0;
}

View File

@ -160,7 +160,7 @@ struct sinfo
int nformi(const sinfo * si, char * str, int v, bool s) int nformi(const sinfo * si, char * str, int v, bool s)
{ {
char * sp = str; char buffer[16];
unsigned int u = v; unsigned int u = v;
bool neg = false; bool neg = false;
@ -171,10 +171,7 @@ int nformi(const sinfo * si, char * str, int v, bool s)
u = -v; u = -v;
} }
char b = si->width; char i = 16;
if (b < 10)
b = 10;
char i = b;
while (u > 0) while (u > 0)
{ {
int c = u % si->base; int c = u % si->base;
@ -182,40 +179,40 @@ int nformi(const sinfo * si, char * str, int v, bool s)
c += 'A' - 10; c += 'A' - 10;
else else
c += '0'; c += '0';
sp[--i] = c; buffer[--i] = c;
u /= si->base; u /= si->base;
} }
char digits = si->precision != 255 ? b - si->precision : b - 1; char digits = si->precision != 255 ? 16 - si->precision : 15;
while (i > digits) while (i > digits)
sp[--i] = '0'; buffer[--i] = '0';
if (si->prefix && si->base == 16) if (si->prefix && si->base == 16)
{ {
sp[--i] = 'X'; buffer[--i] = 'X';
sp[--i] = '0'; buffer[--i] = '0';
} }
if (neg) if (neg)
sp[--i] = '-'; buffer[--i] = '-';
else if (si->sign) else if (si->sign)
sp[--i] = '+'; buffer[--i] = '+';
char j = 0; char j = 0;
if (si->left) if (si->left)
{ {
while (i < b) while (i < 16)
sp[j++] = sp[i++]; str[j++] = buffer[i++];
while (j < si->width) while (j < si->width)
sp[j++] = si->fill; str[j++] = si->fill;
} }
else else
{ {
while (i + si->width > b) while (i + si->width > 16)
sp[--i] = si->fill; buffer[--i] = si->fill;
while (i < b) while (i < 16)
sp[j++] = sp[i++]; str[j++] = buffer[i++];
} }
return j; return j;
@ -223,7 +220,7 @@ int nformi(const sinfo * si, char * str, int v, bool s)
int nforml(const sinfo * si, char * str, long v, bool s) int nforml(const sinfo * si, char * str, long v, bool s)
{ {
char * sp = str; char buffer[16];
unsigned long u = v; unsigned long u = v;
bool neg = false; bool neg = false;
@ -234,10 +231,7 @@ int nforml(const sinfo * si, char * str, long v, bool s)
u = -v; u = -v;
} }
char b = si->width; char i = 16;
if (b < 16)
b = 16;
char i = b;
while (u > 0) while (u > 0)
{ {
@ -246,45 +240,49 @@ int nforml(const sinfo * si, char * str, long v, bool s)
c += 'A' - 10; c += 'A' - 10;
else else
c += '0'; c += '0';
sp[--i] = c; buffer[--i] = c;
u /= si->base; u /= si->base;
} }
char digits = si->precision != 255 ? b - si->precision : b - 1; char digits = si->precision != 255 ? 16 - si->precision : 15;
while (i > digits) while (i > digits)
sp[--i] = '0'; buffer[--i] = '0';
if (si->prefix && si->base == 16) if (si->prefix && si->base == 16)
{ {
sp[--i] = 'X'; buffer[--i] = 'X';
sp[--i] = '0'; buffer[--i] = '0';
} }
if (neg) if (neg)
sp[--i] = '-'; buffer[--i] = '-';
else if (si->sign) else if (si->sign)
sp[--i] = '+'; buffer[--i] = '+';
char j = 0; char j = 0;
if (si->left) if (si->left)
{ {
while (i < b) while (i < 16)
sp[j++] = sp[i++]; str[j++] = buffer[i++];
while (j < si->width) while (j < si->width)
sp[j++] = si->fill; str[j++] = si->fill;
} }
else else
{ {
while (i + si->width > b) while (i + si->width > 16)
sp[--i] = si->fill; buffer[--i] = si->fill;
while (i < b) while (i < 16)
sp[j++] = sp[i++]; str[j++] = buffer[i++];
} }
return j; return j;
} }
static float fround5[] = {
0.5e-0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6
};
int nformf(const sinfo * si, char * str, float f, char type) int nformf(const sinfo * si, char * str, float f, char type)
{ {
char * sp = str; char * sp = str;
@ -349,12 +347,14 @@ int nformf(const sinfo * si, char * str, float f, char type)
f /= 10.0; f /= 10.0;
exp++; exp++;
} }
digits = fdigits + exp + 1; digits = fdigits + exp + 1;
float r = 0.5; if (digits < 7)
for(char i=1; i<digits; i++) f += fround5[digits - 1];
r /= 10.0; else
f += r; f += fround5[6];
if (f >= 10.0) if (f >= 10.0)
{ {
f /= 10.0; f /= 10.0;
@ -363,10 +363,11 @@ int nformf(const sinfo * si, char * str, float f, char type)
} }
else else
{ {
float r = 0.5; if (digits < 7)
for(char i=0; i<fdigits; i++) f += fround5[digits - 1];
r /= 10.0; else
f += r; f += fround5[6];
if (f >= 10.0) if (f >= 10.0)
{ {
f /= 10.0; f /= 10.0;
@ -387,11 +388,16 @@ int nformf(const sinfo * si, char * str, float f, char type)
{ {
if (i == pdigits) if (i == pdigits)
sp[d++] = '.'; sp[d++] = '.';
if (i > 6)
sp[d++] = '0';
else
{
int c = (int)f; int c = (int)f;
f -= (float)c; f -= (float)c;
f *= 10.0; f *= 10.0;
sp[d++] = c + '0'; sp[d++] = c + '0';
} }
}
if (fexp) if (fexp)
{ {

View File

@ -13811,7 +13811,7 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
return true; return true;
} }
if (!(mIns[from].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) if (!(mIns[from].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)) && !(mIns[to].mLive & LIVE_CPU_REG_C))
{ {
start = from; start = from;
while (start > 0 && mIns[start - 1].mType != ASMIT_LDA && (mIns[start - 1].mMode == ASMIM_IMMEDIATE || mIns[start - 1].mMode == ASMIM_IMPLIED)) while (start > 0 && mIns[start - 1].mType != ASMIT_LDA && (mIns[start - 1].mMode == ASMIM_IMMEDIATE || mIns[start - 1].mMode == ASMIM_IMPLIED))
@ -19158,6 +19158,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
} }
CheckLive(); CheckLive();
#if 1 #if 1
int taxPos = -1, tayPos = -1; int taxPos = -1, tayPos = -1;
for (int i = 0; i < mIns.Size(); i++) for (int i = 0; i < mIns.Size(); i++)
@ -19209,6 +19210,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
} }
CheckLive(); CheckLive();
#endif
#if 1
for (int i = 0; i + 2 < mIns.Size(); i++) for (int i = 0; i + 2 < mIns.Size(); i++)
{ {
if (mIns[i].mType == ASMIT_TAX && mIns[i + 1].mType == ASMIT_TAY || if (mIns[i].mType == ASMIT_TAX && mIns[i + 1].mType == ASMIT_TAY ||
@ -19222,6 +19226,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#endif #endif
#if 1 #if 1
if (pass > 1) if (pass > 1)
{ {