Skip to content

Commit 2a963bf

Browse files
committed
Memory safety improvements
1 parent 0a3bc7e commit 2a963bf

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed

ini_parser.h

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
225225
return false;
226226
}
227227

228+
ctx->content = NULL;
229+
ctx->sections = NULL;
228230
ctx->content = calloc(1, length + 1);
229231

230232
if(!ctx->content)
@@ -238,6 +240,7 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
238240
ini_section_t *currentSection = NULL;
239241
char line[INI_MAX_LINE_LENGTH];
240242
const char *ptr = ctx->content;
243+
bool has_valid_entries = false;
241244

242245
while(*ptr)
243246
{
@@ -294,6 +297,7 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
294297
}
295298

296299
currentSection = newSection;
300+
has_valid_entries = true;
297301
}
298302
else if(type == INI_LINE_KEY_VALUE && currentSection)
299303
{
@@ -326,6 +330,8 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
326330

327331
last->next = newKv;
328332
}
333+
334+
has_valid_entries = true;
329335
}
330336

331337
if(*ptr)
@@ -334,6 +340,12 @@ bool ini_initialize(ini_context_t *ctx, const char *content, size_t length)
334340
}
335341
}
336342

343+
if(!has_valid_entries)
344+
{
345+
ini_cleanup(ctx);
346+
return false;
347+
}
348+
337349
return true;
338350
}
339351

@@ -344,23 +356,28 @@ void ini_cleanup(ini_context_t *ctx)
344356
return;
345357
}
346358

347-
free(ctx->content);
359+
if(ctx->content)
360+
{
361+
free(ctx->content);
362+
ctx->content = NULL;
363+
}
364+
348365
ini_section_t *section = ctx->sections;
349366

350367
while(section)
351368
{
352-
ini_section_t *nextSection = section->next;
369+
ini_section_t *next_section = section->next;
353370
ini_keyvalue_t *kv = section->keyValues;
354371

355372
while(kv)
356373
{
357-
ini_keyvalue_t *nextKv = kv->next;
374+
ini_keyvalue_t *next_kv = kv->next;
358375
free(kv);
359-
kv = nextKv;
376+
kv = next_kv;
360377
}
361378

362379
free(section);
363-
section = nextSection;
380+
section = next_section;
364381
}
365382

366383
ctx->sections = NULL;

ini_parser_tests.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,33 @@ TEST_F(IniParserTest, KeyWithoutSection)
226226
EXPECT_TRUE(ini_hasKey(&ctx, "section1", "key2"));
227227
}
228228

229+
TEST_F(IniParserTest, HandlesCRLFFiles)
230+
{
231+
const char *content = "[section]\r\nkey=value\r\n";
232+
ASSERT_TRUE(LoadIniContent(content));
233+
char value[INI_MAX_LINE_LENGTH];
234+
EXPECT_TRUE(ini_getValue(&ctx, "section", "key", value, sizeof(value)));
235+
EXPECT_STREQ(value, "value");
236+
}
237+
238+
TEST_F(IniParserTest, MaxLineLengthHandling)
239+
{
240+
std::string long_line(INI_MAX_LINE_LENGTH * 2, 'a');
241+
std::string content = "[section]\n" + long_line + "\n";
242+
ASSERT_TRUE(ini_initialize(&ctx, content.c_str(), content.size()));
243+
}
244+
245+
TEST_F(IniParserTest, MemorySafetyOnInvalidInput)
246+
{
247+
const char *content = "[section\nkey=value"; // Missing ] and unterminated quote
248+
ini_context_t ctx;
249+
EXPECT_FALSE(ini_initialize(&ctx, content, strlen(content)));
250+
// Safe to call multiple times
251+
ini_cleanup(&ctx);
252+
ini_cleanup(&ctx); // Double call test
253+
ini_cleanup(&ctx); // Triple call test
254+
}
255+
229256
TEST_F(IniParserTest, ComprehensiveParsing)
230257
{
231258
const char *content = R"INI(

0 commit comments

Comments
 (0)