Skip to content

Commit d278023

Browse files
authored
Merge pull request #63 from masatake/fix-integer-overflow
Fix an integer overflow occurring when a tag has too many fields
2 parents ea0aa55 + 4086de9 commit d278023

6 files changed

Lines changed: 101 additions & 2 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ tests/test-api-tagsOpen
4141
tests/test-api-tagsSetSortType
4242
tests/test-fix-large-tags
4343
tests/test-fix-null-deref
44+
tests/test-fix-too-many-fields
4445
tests/test-fix-unescaping
4546
tests/test-fix-unescaping-input-fields
4647
tests/test-fix-unescaping-input-fields-exuberant

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
4.67user 0.19system 0:04.89elapsed 99%CPU (0avgtext+0avgdata 2819612maxresident)k
1818
0inputs+0outputs (0major+44137minor)pagefaults 0swaps
1919
```
20+
- fix an integer overflow occurring when a tag has too many fields.
21+
22+
The original issue was reported by Arthur Chan
23+
<arthur.chan@adalogics.com> from Ada Logics in collaboration with
24+
Claude and Anthropic Research.
2025

2126
# Version 0.4.0
2227

readtags.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,15 @@ static tagResult growFields (tagFile *const file)
421421
{
422422
tagResult result = TagFailure;
423423
unsigned short newCount = (unsigned short) 2 * file->fields.max;
424-
tagExtensionField *newFields = (tagExtensionField*)
424+
tagExtensionField *newFields;
425+
426+
if (!(newCount > file->fields.max)) {
427+
errno = EOVERFLOW;
428+
perror ("too many extension fields");
429+
goto out; /* integer overflow */
430+
}
431+
432+
newFields = (tagExtensionField*)
425433
realloc (file->fields.list, newCount * sizeof (tagExtensionField));
426434
if (newFields == NULL)
427435
perror ("too many extension fields");
@@ -431,6 +439,8 @@ static tagResult growFields (tagFile *const file)
431439
file->fields.max = newCount;
432440
result = TagSuccess;
433441
}
442+
443+
out:
434444
return result;
435445
}
436446

@@ -513,7 +523,7 @@ static tagResult parseExtensionFields (tagFile *const file, tagEntry *const entr
513523
{
514524
if (growFields (file) != TagSuccess)
515525
{
516-
*err = ENOMEM;
526+
*err = errno;
517527
return TagFailure;
518528
}
519529
}

tests/Makefile.am

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ TESTS = \
1616
test-fix-unescaping-input-fields-no-mode \
1717
test-fix-unescaping-input-fields-backslash \
1818
test-fix-unescaping-input-fields-no-filesep \
19+
test-fix-too-many-fields \
1920
\
2021
$(NULL)
2122

@@ -37,6 +38,7 @@ check_PROGRAMS = \
3738
test-fix-unescaping-input-fields-no-mode \
3839
test-fix-unescaping-input-fields-backslash \
3940
test-fix-unescaping-input-fields-no-filesep \
41+
test-fix-too-many-fields \
4042
\
4143
$(NULL)
4244

@@ -120,3 +122,7 @@ EXTRA_DIST += unescaping-input-fields-backslash.tags
120122
test_fix_unescaping_input_fields_no_filesep = test-fix-unescaping-input-fields-no-filesep.c
121123
test_fix_unescaping_input_fields_no_filesep_DEPENDENCIES = $(DEPS)
122124
EXTRA_DIST += unescaping-input-fields-no-filesep.tags
125+
126+
test_fix_too_many_fields = test-fix-too-many-fields.c
127+
test_fix_too_many_fields_DEPENDENCIES = $(DEPS)
128+
EXTRA_DIST += too-many-fields.tags

tests/test-fix-too-many-fields.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2026, Masatake YAMATO
3+
*
4+
* This source code is released into the public domain.
5+
*
6+
* Testing the fix for handling unescaping
7+
*/
8+
9+
#include "readtags.h"
10+
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
#include <unistd.h>
14+
#include <errno.h>
15+
16+
int
17+
main (void)
18+
{
19+
char *srcdir = getenv ("srcdir");
20+
if (srcdir)
21+
{
22+
if (chdir (srcdir) == -1)
23+
{
24+
perror ("chdir");
25+
return 99;
26+
}
27+
}
28+
29+
tagFile *t;
30+
tagFileInfo info;
31+
32+
const char *tags0 = "./too-many-fields.tags";
33+
t = tagsOpen (tags0, &info);
34+
if (t == NULL
35+
|| info.status.opened == 0)
36+
{
37+
fprintf (stderr, "unexpected result (t: %p, opened: %d)\n",
38+
t, info.status.opened);
39+
return 1;
40+
}
41+
fprintf (stderr, "ok\n");
42+
43+
tagEntry e;
44+
tagResult r;
45+
int err;
46+
47+
r = tagsFirst (t, &e);
48+
if (r != TagFailure)
49+
{
50+
fprintf (stderr, "unexpected successful returned from tagsFirst\n");
51+
return 1;
52+
}
53+
54+
err = tagsGetErrno (t);
55+
if (err != EOVERFLOW)
56+
{
57+
if (err > 0)
58+
{
59+
errno = err;
60+
perror("tagsFirst");
61+
}
62+
fprintf (stderr, "unexpected errno returned from tagsFirst: %d\n", err);
63+
return 1;
64+
}
65+
66+
r = tagsClose(t);
67+
if (r != TagSuccess)
68+
{
69+
fprintf (stderr, "error in tagsClose\n");
70+
return 1;
71+
}
72+
73+
return 0;
74+
}

tests/too-many-fields.tags

Lines changed: 3 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)