Fix segfault when IniFile_Load is called with invalid input (#5331)

* Fix segfault when IniFile_Load is called with invalid input

* Fix leak in TestIni.c third testcase

* TestIni.c: Refactor in order to avoid some old compilers errors
This commit is contained in:
Kubistika 2019-04-08 10:26:46 +03:00 committed by akallabeth
parent 7ae72ee512
commit 967f2aefac
2 changed files with 68 additions and 55 deletions

View File

@ -390,6 +390,10 @@ int IniFile_Load(wIniFile* ini)
else else
{ {
separator = strchr(line, '='); separator = strchr(line, '=');
if (separator == NULL)
return -1;
end = separator; end = separator;
while ((&end[-1] > line) && ((end[-1] == ' ') || (end[-1] == '\t'))) while ((&end[-1] > line) && ((end[-1] == ' ') || (end[-1] == '\t')))

View File

@ -1,31 +1,43 @@
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/ini.h> #include <winpr/ini.h>
const char TEST_INI_01[] = const char TEST_INI_01[] =
"; This is a sample .ini config file\n" "; This is a sample .ini config file\n"
"\n" "\n"
"[first_section]\n" "[first_section]\n"
"one = 1\n" "one = 1\n"
"five = 5\n" "five = 5\n"
"animal = BIRD\n" "animal = BIRD\n"
"\n" "\n"
"[second_section]\n" "[second_section]\n"
"path = \"/usr/local/bin\"\n" "path = \"/usr/local/bin\"\n"
"URL = \"http://www.example.com/~username\"\n" "URL = \"http://www.example.com/~username\"\n"
"\n"; "\n";
const char TEST_INI_02[] = const char TEST_INI_02[] =
"[FreeRDS]\n" "[FreeRDS]\n"
"prefix=\"/usr/local\"\n" "prefix=\"/usr/local\"\n"
"bindir=\"bin\"\n" "bindir=\"bin\"\n"
"sbindir=\"sbin\"\n" "sbindir=\"sbin\"\n"
"libdir=\"lib\"\n" "libdir=\"lib\"\n"
"datarootdir=\"share\"\n" "datarootdir=\"share\"\n"
"localstatedir=\"var\"\n" "localstatedir=\"var\"\n"
"sysconfdir=\"etc\"\n" "sysconfdir=\"etc\"\n"
"\n"; "\n";
const char TEST_INI_03[] =
"[FreeRDS]\n"
"prefix=\"/usr/local\"\n"
"bindir=\"bin\"\n"
"# some illegal string\n"
"sbindir=\"sbin\"\n"
"libdir=\"lib\"\n"
"invalid key-value pair\n"
"datarootdir=\"share\"\n"
"localstatedir=\"var\"\n"
"sysconfdir=\"etc\"\n"
"\n";
int TestIni(int argc, char* argv[]) int TestIni(int argc, char* argv[])
{ {
@ -37,101 +49,98 @@ int TestIni(int argc, char* argv[])
const char* sValue; const char* sValue;
char** keyNames; char** keyNames;
char** sectionNames; char** sectionNames;
/* First Sample */ /* First Sample */
ini = IniFile_New(); ini = IniFile_New();
IniFile_ReadBuffer(ini, TEST_INI_01); IniFile_ReadBuffer(ini, TEST_INI_01);
sectionNames = IniFile_GetSectionNames(ini, &nSections); sectionNames = IniFile_GetSectionNames(ini, &nSections);
for (i = 0; i < nSections; i++) for (i = 0; i < nSections; i++)
{ {
keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys); keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys);
printf("[%s]\n", sectionNames[i]); printf("[%s]\n", sectionNames[i]);
for (j = 0; j < nKeys; j++) for (j = 0; j < nKeys; j++)
{ {
sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]); sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]);
printf("%s = %s\n", keyNames[j], sValue); printf("%s = %s\n", keyNames[j], sValue);
} }
free(keyNames); free(keyNames);
} }
free(sectionNames);
free(sectionNames);
iValue = IniFile_GetKeyValueInt(ini, "first_section", "one"); iValue = IniFile_GetKeyValueInt(ini, "first_section", "one");
if (iValue != 1) if (iValue != 1)
{ {
printf("IniFile_GetKeyValueInt failure\n"); printf("IniFile_GetKeyValueInt failure\n");
return -1; return -1;
} }
iValue = IniFile_GetKeyValueInt(ini, "first_section", "five"); iValue = IniFile_GetKeyValueInt(ini, "first_section", "five");
if (iValue != 5) if (iValue != 5)
{ {
printf("IniFile_GetKeyValueInt failure\n"); printf("IniFile_GetKeyValueInt failure\n");
return -1; return -1;
} }
sValue = IniFile_GetKeyValueString(ini, "first_section", "animal"); sValue = IniFile_GetKeyValueString(ini, "first_section", "animal");
if (strcmp(sValue, "BIRD") != 0) if (strcmp(sValue, "BIRD") != 0)
{ {
printf("IniFile_GetKeyValueString failure\n"); printf("IniFile_GetKeyValueString failure\n");
return -1; return -1;
} }
sValue = IniFile_GetKeyValueString(ini, "second_section", "path"); sValue = IniFile_GetKeyValueString(ini, "second_section", "path");
if (strcmp(sValue, "/usr/local/bin") != 0) if (strcmp(sValue, "/usr/local/bin") != 0)
{ {
printf("IniFile_GetKeyValueString failure\n"); printf("IniFile_GetKeyValueString failure\n");
return -1; return -1;
} }
sValue = IniFile_GetKeyValueString(ini, "second_section", "URL"); sValue = IniFile_GetKeyValueString(ini, "second_section", "URL");
if (strcmp(sValue, "http://www.example.com/~username") != 0) if (strcmp(sValue, "http://www.example.com/~username") != 0)
{ {
printf("IniFile_GetKeyValueString failure\n"); printf("IniFile_GetKeyValueString failure\n");
return -1; return -1;
} }
IniFile_Free(ini); IniFile_Free(ini);
/* Second Sample */ /* Second Sample */
ini = IniFile_New(); ini = IniFile_New();
IniFile_ReadBuffer(ini, TEST_INI_02); IniFile_ReadBuffer(ini, TEST_INI_02);
sectionNames = IniFile_GetSectionNames(ini, &nSections); sectionNames = IniFile_GetSectionNames(ini, &nSections);
for (i = 0; i < nSections; i++) for (i = 0; i < nSections; i++)
{ {
keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys); keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys);
printf("[%s]\n", sectionNames[i]); printf("[%s]\n", sectionNames[i]);
for (j = 0; j < nKeys; j++) for (j = 0; j < nKeys; j++)
{ {
sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]); sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]);
printf("%s = %s\n", keyNames[j], sValue); printf("%s = %s\n", keyNames[j], sValue);
} }
free(keyNames); free(keyNames);
} }
free(sectionNames); free(sectionNames);
IniFile_Free(ini); IniFile_Free(ini);
/* Third sample - invalid input */
ini = IniFile_New();
if (IniFile_ReadBuffer(ini, TEST_INI_03) != -1)
{
IniFile_Free(ini);
return -1;
}
IniFile_Free(ini);
return 0; return 0;
} }