Skip to content

Commit 1d2f619

Browse files
committed
Fixed bug #61964 (finfo_open with directory cause invalid free)
1 parent c973fef commit 1d2f619

File tree

2 files changed

+89
-7
lines changed

2 files changed

+89
-7
lines changed

ext/fileinfo/libmagic/apprentice.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ private int
753753
apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
754754
const char *fn, int action)
755755
{
756-
int errs = 0;
756+
int errs = 0, mflen = 0;
757757
struct magic_entry *marray;
758758
uint32_t marraycount, i, mentrycount = 0, starttest;
759759
size_t files = 0, maxfiles = 0;
@@ -782,7 +782,7 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
782782
goto out;
783783
}
784784
while ((d = readdir(dir)) != NULL) {
785-
if (snprintf(mfn, sizeof(mfn), "%s/%s", fn, d->d_name) < 0) {
785+
if ((mflen = snprintf(mfn, sizeof(mfn), "%s/%s", fn, d->d_name)) < 0) {
786786
file_oomem(ms,
787787
strlen(fn) + strlen(d->d_name) + 2);
788788
errs++;
@@ -804,14 +804,14 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
804804
goto out;
805805
}
806806
}
807-
filearr[files++] = mfn;
807+
filearr[files++] = estrndup(mfn, mflen);
808808
}
809809
closedir(dir);
810810
qsort(filearr, files, sizeof(*filearr), cmpstrp);
811811
for (i = 0; i < files; i++) {
812812
load_1(ms, action, filearr[i], &errs, &marray,
813813
&marraycount);
814-
free(filearr[i]);
814+
efree(filearr[i]);
815815
}
816816
free(filearr);
817817
} else
@@ -886,9 +886,14 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
886886
mentrycount += marray[i].cont_count;
887887
}
888888
out:
889-
for (i = 0; i < marraycount; i++)
890-
efree(marray[i].mp);
891-
efree(marray);
889+
for (i = 0; i < marraycount; i++) {
890+
if (marray[i].mp) {
891+
efree(marray[i].mp);
892+
}
893+
}
894+
if (marray) {
895+
efree(marray);
896+
}
892897
if (errs) {
893898
*magicp = NULL;
894899
*nmagicp = 0;
@@ -1165,6 +1170,9 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
11651170
return -1;
11661171
}
11671172
me = &(*mentryp)[*nmentryp - 1];
1173+
if (me->mp == NULL) {
1174+
return -1;
1175+
}
11681176
if (me->cont_count == me->max_count) {
11691177
struct magic *nm;
11701178
size_t cnt = me->max_count + ALLOC_CHUNK;
@@ -1329,6 +1337,10 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
13291337
if (m->type == FILE_INVALID) {
13301338
if (ms->flags & MAGIC_CHECK)
13311339
file_magwarn(ms, "type `%s' invalid", l);
1340+
if (me->mp) {
1341+
efree(me->mp);
1342+
me->mp = NULL;
1343+
}
13321344
return -1;
13331345
}
13341346

@@ -2219,6 +2231,7 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
22192231
mm = emalloc((size_t)st.sb.st_size);
22202232
if (php_stream_read(stream, mm, (size_t)st.sb.st_size) != (size_t)st.sb.st_size) {
22212233
file_badread(ms);
2234+
ret = 1;
22222235
goto error1;
22232236
}
22242237
ret = 1;

ext/fileinfo/tests/bug61964.phpt

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
Bug #61964 (finfo_open with directory cause invalid free)
3+
--SKIPIF--
4+
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
8+
$magic_file = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'magic';
9+
10+
$ret = @finfo_open(FILEINFO_NONE, $magic_file . ".non-exits");
11+
var_dump($ret);
12+
13+
$dir = __DIR__ . "/test-folder";
14+
@mkdir($dir);
15+
16+
$magic_file_copy = $dir . "/magic.copy";
17+
$magic_file_copy2 = $magic_file_copy . "2";
18+
copy($magic_file, $magic_file_copy);
19+
copy($magic_file, $magic_file_copy2);
20+
21+
$ret = finfo_open(FILEINFO_NONE, $dir);
22+
var_dump($ret);
23+
24+
$ret = @finfo_open(FILEINFO_NONE, $dir);
25+
var_dump($ret);
26+
27+
$ret = @finfo_open(FILEINFO_NONE, $dir. "/non-exits-dir");
28+
var_dump($ret);
29+
30+
// write some test files to test folder
31+
file_put_contents($dir . "/test1.txt", "string\n> Core\n> Me");
32+
file_put_contents($dir . "/test2.txt", "a\nb\n");
33+
@mkdir($dir . "/test-inner-folder");
34+
35+
finfo_open(FILEINFO_NONE, $dir);
36+
echo "DONE: testing dir with files\n";
37+
38+
rmdir($dir . "/test-inner-folder");
39+
unlink($dir . "/test1.txt");
40+
unlink($dir . "/test2.txt");
41+
42+
unlink($magic_file_copy);
43+
unlink($magic_file_copy2);
44+
rmdir($dir);
45+
?>
46+
===DONE===
47+
--EXPECTF--
48+
bool(false)
49+
resource(%d) of type (file_info)
50+
resource(%d) of type (file_info)
51+
bool(false)
52+
53+
Notice: finfo_open(): Warning: offset `string' invalid in %sbug61964.php on line %d
54+
55+
Notice: finfo_open(): Warning: offset ` Core' invalid in %sbug61964.php on line %d
56+
57+
Notice: finfo_open(): Warning: type `Core' invalid in %sbug61964.php on line %d
58+
59+
Notice: finfo_open(): Warning: offset `a' invalid in %sbug61964.php on line %d
60+
61+
Notice: finfo_open(): Warning: type `a' invalid in %sbug61964.php on line %d
62+
63+
Notice: finfo_open(): Warning: offset `b' invalid in %sbug61964.php on line %d
64+
65+
Notice: finfo_open(): Warning: type `b' invalid in %sbug61964.php on line %d
66+
67+
Warning: finfo_open(): Failed to load magic database at '%stest-folder'. in %sbug61964.php on line %d
68+
DONE: testing dir with files
69+
===DONE===

0 commit comments

Comments
 (0)