diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2013-01-08 13:01:48 -0600 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2013-01-08 13:03:35 -0600 |
commit | dc21ed28d69df279c6068d9cae862e02af72815f (patch) | |
tree | 761a9c0feea8b8abf3cc4f1aa4e28fe215b41988 | |
parent | 4e6c7d0827c5b3b20205521bf9bd2e94e704b36d (diff) | |
download | fontconfig-dc21ed28d69df279c6068d9cae862e02af72815f.tar.gz |
Fix memory corruption!
In FcStrListCreate() we were increasing reference count of set,
however, if set had a const reference (which is the case for list
of languages), and with multiple threads, the const ref (-1) was
getting up to 1 and then a decrease was destroying the set. Ouch.
Here's the valgrind error, which took me quite a few hours of
running to catch:
==4464== Invalid read of size 4
==4464== at 0x4E58FF3: FcStrListNext (fcstr.c:1256)
==4464== by 0x4E3F11D: FcConfigSubstituteWithPat (fccfg.c:1508)
==4464== by 0x4E3F8F4: FcConfigSubstitute (fccfg.c:1729)
==4464== by 0x4009FA: test_match (simple-pthread-test.c:53)
==4464== by 0x400A6E: run_test_in_thread (simple-pthread-test.c:68)
==4464== by 0x507EE99: start_thread (pthread_create.c:308)
==4464== Address 0x6bc0b44 is 4 bytes inside a block of size 24 free'd
==4464== at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4464== by 0x4E58F84: FcStrSetDestroy (fcstr.c:1236)
==4464== by 0x4E3F0C6: FcConfigSubstituteWithPat (fccfg.c:1507)
==4464== by 0x4E3F8F4: FcConfigSubstitute (fccfg.c:1729)
==4464== by 0x4009FA: test_match (simple-pthread-test.c:53)
==4464== by 0x400A6E: run_test_in_thread (simple-pthread-test.c:68)
==4464== by 0x507EE99: start_thread (pthread_create.c:308)
Thread test is running happily now. Will add the test in a moment.
-rw-r--r-- | src/fcstr.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/fcstr.c b/src/fcstr.c index cdab383..414d6dd 100644 --- a/src/fcstr.c +++ b/src/fcstr.c @@ -1217,6 +1217,17 @@ FcStrSetDel (FcStrSet *set, const FcChar8 *s) return FcFalse; } +/* TODO Make public */ +static FcStrSet * +FcStrSetReference (FcStrSet *set) +{ + if (FcRefIsConst (&set->ref)) + return set; + + FcRefInc (&set->ref); + return set; +} + void FcStrSetDestroy (FcStrSet *set) { @@ -1245,7 +1256,7 @@ FcStrListCreate (FcStrSet *set) if (!list) return 0; list->set = set; - FcRefInc (&set->ref); + FcStrSetReference (set); list->n = 0; return list; } |