As reported by Matthias Schwarzott <zzam@gentoo.org>. Testcase patch from him. The fix is
for check_CFSI_related_invariants() to avoid checking for overlaps against DebugInfos that are
in 'archived' status, since -- if a previously dlopened-and-then-dlclosed object is later
re-dlopened -- this may cause an overlap between the active and archived DebugInfos, which
is of no consequence. If the kernel maps the object to the same VMA the second time around
then there will *certainly* be an overlap.
/* invariant (1) */
for (di2 = debugInfo_list; di2; di2 = di2->next) {
- if (di2 == di)
+ if (di2 == di || is_DebugInfo_archived(di2))
continue;
for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
const DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
or the normal case, which is the AND of the following:
(0) size of at least one rx mapping > 0
- (1) no two DebugInfos with some rx mapping of size > 0
+ (1) no two non-archived DebugInfos with some rx mapping of size > 0
have overlapping rx mappings
(2) [cfsi_minavma,cfsi_maxavma] does not extend beyond
[avma,+size) of one rx mapping; that is, the former
Conditional jump or move depends on uninitialised value(s)
at 0x........: jmp_on_uninit (dlclose_leak_so.c:10)
- by 0x........: main (dlclose_leak.c:26)
+ by 0x........: main (dlclose_leak.c:29)
Invalid read of size 1
- at 0x........: main (dlclose_leak.c:29)
+ at 0x........: main (dlclose_leak.c:32)
Address 0x........ is 1 bytes before a block of size 1 alloc'd
at 0x........: malloc (vg_replace_malloc.c:...)
...
- by 0x........: main (dlclose_leak.c:27)
+ by 0x........: main (dlclose_leak.c:30)
done!
-1 bytes in 1 blocks are definitely lost in loss record ... of ...
+2 bytes in 2 blocks are definitely lost in loss record ... of ...
at 0x........: malloc (vg_replace_malloc.c:...)
...
- by 0x........: main (dlclose_leak.c:27)
+ by 0x........: main (dlclose_leak.c:30)
int (*jmp_on_uninit)(void);
char* (*alloc_1_byte)(void);
-int main(int argc, char** argv) {
- char* memToLeak;
- char x __attribute__((unused));
- void* handle = dlopen("./dlclose_leak_so.so", RTLD_NOW);
- if(!handle) {
- printf("FAILURE to dlopen dlclose_leak_so.so\n");
- return EXIT_FAILURE;
+int main(int argc, char** argv)
+{
+ for (int i = 0; i < 2; ++i)
+ {
+ char* memToLeak;
+ char x __attribute__((unused));
+ void* handle = dlopen("./dlclose_leak_so.so", RTLD_NOW);
+ if(!handle) {
+ printf("FAILURE to dlopen dlclose_leak_so.so\n");
+ return EXIT_FAILURE;
+ }
+ jmp_on_uninit = dlsym(handle,"jmp_on_uninit");
+ //fprintf(stderr, "jmp_on_uninit: %p\n", jmp_on_uninit);
+ assert(jmp_on_uninit);
+ alloc_1_byte = dlsym(handle,"alloc_1_byte");
+ //fprintf(stderr, "alloc_1_byte: %p\n", alloc_1_byte);
+ assert(alloc_1_byte);
+ (void)jmp_on_uninit();
+ memToLeak = alloc_1_byte();
+ dlclose(handle);
+ x = memToLeak[-1];
}
- jmp_on_uninit = dlsym(handle,"jmp_on_uninit");
- //fprintf(stderr, "jmp_on_uninit: %p\n", jmp_on_uninit);
- assert(jmp_on_uninit);
- alloc_1_byte = dlsym(handle,"alloc_1_byte");
- //fprintf(stderr, "alloc_1_byte: %p\n", alloc_1_byte);
- assert(alloc_1_byte);
- (void)jmp_on_uninit();
- memToLeak = alloc_1_byte();
- dlclose(handle);
- x = memToLeak[-1];
fprintf(stderr, "done!\n");
return (EXIT_SUCCESS);
}
Conditional jump or move depends on uninitialised value(s)
at 0x........: jmp_on_uninit (dlclose_leak_so.c:10)
- by 0x........: main (dlclose_leak.c:26)
+ by 0x........: main (dlclose_leak.c:29)
Invalid read of size 1
- at 0x........: main (dlclose_leak.c:29)
+ at 0x........: main (dlclose_leak.c:32)
Address 0x........ is 1 bytes before a block of size 1 alloc'd
at 0x........: malloc (vg_replace_malloc.c:...)
by 0x........: alloc_1_byte (dlclose_leak_so.c:20)
- by 0x........: main (dlclose_leak.c:27)
+ by 0x........: main (dlclose_leak.c:30)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: jmp_on_uninit (dlclose_leak_so.c:10)
+ by 0x........: main (dlclose_leak.c:29)
done!
1 bytes in 1 blocks are definitely lost in loss record ... of ...
at 0x........: malloc (vg_replace_malloc.c:...)
by 0x........: alloc_1_byte (dlclose_leak_so.c:20)
- by 0x........: main (dlclose_leak.c:27)
+ by 0x........: main (dlclose_leak.c:30)
+
+1 bytes in 1 blocks are definitely lost in loss record ... of ...
+ at 0x........: malloc (vg_replace_malloc.c:...)
+ by 0x........: alloc_1_byte (dlclose_leak_so.c:20)
+ by 0x........: main (dlclose_leak.c:30)