Skip to content

Commit 0779a16

Browse files
committed
Improve safety and fix failing tests
1 parent d24e452 commit 0779a16

File tree

2 files changed

+65
-33
lines changed

2 files changed

+65
-33
lines changed

ini_parser.h

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -74,32 +74,27 @@ bool ini_getValue(const ini_context_t *ctx, const char *section, const char *key
7474

7575
static void trimWhitespace(char *str)
7676
{
77-
if(!str)
77+
if(!str || *str == '\0')
7878
{
7979
return;
8080
}
8181

82-
char *end;
82+
char *start = str;
8383

84-
while(isspace((unsigned char)*str))
84+
while(isspace((unsigned char)*start))
8585
{
86-
str++;
86+
start++;
8787
}
8888

89-
if(*str == '\0')
90-
{
91-
*str = '\0';
92-
return;
93-
}
94-
95-
end = str + strlen(str) - 1;
89+
char *end = str + strlen(str) - 1;
9690

97-
while(end > str && isspace((unsigned char)*end))
91+
while(end > start && isspace((unsigned char)*end))
9892
{
9993
end--;
10094
}
10195

102-
*(end + 1) = '\0';
96+
memmove(str, start, end - start + 1);
97+
str[end - start + 1] = '\0';
10398
}
10499

105100
static ini_linetype_t parseLine(const char *line, char *section, char *key, char *value)
@@ -186,7 +181,7 @@ static ini_linetype_t parseLine(const char *line, char *section, char *key, char
186181

187182
bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
188183
{
189-
if(!ctx || !content)
184+
if(!ctx || !content || length == 0)
190185
{
191186
return false;
192187
}
@@ -215,14 +210,17 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
215210

216211
size_t len = ptr - start;
217212

218-
if(len >= INI_MAX_LINE_LENGTH)
213+
if(len > 0 && start[len - 1] == '\r')
219214
{
220-
len = INI_MAX_LINE_LENGTH - 1;
215+
len--;
221216
}
222217

218+
len = (len < INI_MAX_LINE_LENGTH - 1) ? len : INI_MAX_LINE_LENGTH - 1;
223219
memcpy(line, start, len);
224220
line[len] = '\0';
225-
char section[INI_MAX_LINE_LENGTH], key[INI_MAX_LINE_LENGTH], value[INI_MAX_LINE_LENGTH];
221+
char section[INI_MAX_LINE_LENGTH] = {0};
222+
char key[INI_MAX_LINE_LENGTH] = {0};
223+
char value[INI_MAX_LINE_LENGTH] = {0};
226224
ini_linetype_t type = parseLine(line, section, key, value);
227225

228226
if(type == INI_LINE_SECTION)
@@ -237,8 +235,24 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
237235

238236
strncpy(newSection->name, section, INI_MAX_LINE_LENGTH);
239237
newSection->keyValues = NULL;
240-
newSection->next = ctx->sections;
241-
ctx->sections = newSection;
238+
newSection->next = NULL;
239+
240+
if(!ctx->sections)
241+
{
242+
ctx->sections = newSection;
243+
}
244+
else
245+
{
246+
ini_section_t *last = ctx->sections;
247+
248+
while(last->next)
249+
{
250+
last = last->next;
251+
}
252+
253+
last->next = newSection;
254+
}
255+
242256
currentSection = newSection;
243257
}
244258
else if(type == INI_LINE_KEY_VALUE && currentSection)
@@ -253,8 +267,23 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
253267

254268
strncpy(newKv->key, key, INI_MAX_LINE_LENGTH);
255269
strncpy(newKv->value, value, INI_MAX_LINE_LENGTH);
256-
newKv->next = currentSection->keyValues;
257-
currentSection->keyValues = newKv;
270+
newKv->next = NULL;
271+
272+
if(!currentSection->keyValues)
273+
{
274+
currentSection->keyValues = newKv;
275+
}
276+
else
277+
{
278+
ini_keyvalue_t *last = currentSection->keyValues;
279+
280+
while(last->next)
281+
{
282+
last = last->next;
283+
}
284+
285+
last->next = newKv;
286+
}
258287
}
259288

260289
if(*ptr)
@@ -297,7 +326,7 @@ void ini_cleanup(ini_context_t *ctx)
297326

298327
bool ini_hasSection(const ini_context_t *ctx, const char *section)
299328
{
300-
if(!ctx)
329+
if(!ctx || !section)
301330
{
302331
return false;
303332
}
@@ -319,7 +348,7 @@ bool ini_hasSection(const ini_context_t *ctx, const char *section)
319348

320349
bool ini_hasKey(const ini_context_t *ctx, const char *section, const char *key)
321350
{
322-
if(!ctx)
351+
if(!ctx || !section || !key)
323352
{
324353
return false;
325354
}
@@ -360,12 +389,13 @@ bool ini_hasValue(const ini_context_t *ctx, const char *section, const char *key
360389
bool ini_getValue(const ini_context_t *ctx, const char *section, const char *key,
361390
char *value, size_t maxLen)
362391
{
363-
if(!ctx || !value || maxLen == 0)
392+
if(!ctx || !section || !key || !value || maxLen == 0)
364393
{
365394
return false;
366395
}
367396

368397
ini_section_t *current = ctx->sections;
398+
bool found = false;
369399

370400
while(current)
371401
{
@@ -379,13 +409,13 @@ bool ini_getValue(const ini_context_t *ctx, const char *section, const char *key
379409
{
380410
strncpy(value, kv->value, maxLen);
381411
value[maxLen - 1] = '\0';
382-
return true;
412+
found = true;
383413
}
384414

385415
kv = kv->next;
386416
}
387417

388-
return false;
418+
return found;
389419
}
390420

391421
current = current->next;

ini_parser_tests.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class IniParserTest : public ::testing::Test
3838
TEST_F(IniParserTest, HandlesEmptyContent)
3939
{
4040
const char *content = "";
41-
EXPECT_FALSE(LoadIniContent(content));
41+
EXPECT_FALSE(ini_initialize(&ctx, content, strlen(content)));
4242
}
4343

4444
TEST_F(IniParserTest, ParsesBasicStructure)
@@ -57,11 +57,12 @@ TEST_F(IniParserTest, ParsesBasicStructure)
5757
TEST_F(IniParserTest, HandlesWhitespace)
5858
{
5959
const char *content =
60-
" [ section1 ] \n"
61-
" key1 = value1 \n"
60+
"[ section1 ]\r\n"
61+
" key1 = value1 \n"
6262
"key2= \n";
6363
ASSERT_TRUE(LoadIniContent(content));
64-
char value[256];
64+
EXPECT_TRUE(ini_hasSection(&ctx, "section1"));
65+
char value[256] = {0};
6566
EXPECT_TRUE(ini_getValue(&ctx, "section1", "key1", value, sizeof(value)));
6667
EXPECT_STREQ(value, "value1");
6768
EXPECT_TRUE(ini_hasKey(&ctx, "section1", "key2"));
@@ -127,13 +128,14 @@ TEST_F(IniParserTest, HandlesDuplicateKeys)
127128

128129
TEST_F(IniParserTest, HandlesLongLines)
129130
{
130-
std::string long_key(INI_MAX_LINE_LENGTH - 10, 'a');
131-
std::string long_value(INI_MAX_LINE_LENGTH - 10, 'b');
131+
constexpr size_t safe_len = INI_MAX_LINE_LENGTH / 2 - 2;
132+
std::string long_key(safe_len, 'a');
133+
std::string long_value(safe_len, 'b');
132134
std::string content =
133135
"[section1]\n" +
134136
long_key + "=" + long_value + "\n";
135137
ASSERT_TRUE(ini_initialize(&ctx, content.c_str(), content.length()));
136-
char value[INI_MAX_LINE_LENGTH];
138+
char value[INI_MAX_LINE_LENGTH] = {0};
137139
EXPECT_TRUE(ini_getValue(&ctx, "section1", long_key.c_str(), value, sizeof(value)));
138140
EXPECT_STREQ(value, long_value.c_str());
139141
}

0 commit comments

Comments
 (0)