I encountered a segfault in the sial module when repeatedly loading and unloading
a sial script. The bug is repeatable and it always segfaults on the 4th unload.
The bug only triggers if a pathname is specified for the sial script too (just
doing 'load test.sial, unload test.sial, ...' doesn't trigger the problem).
The cause of the problem is that sial_freefile() will free the memory used by the
static and global variable lists but leaves the stale pointer in the fdata object.
This stale pointer is then assumed to be allocated later by sial_inivars().
I've included a patch below to NULL out the static and global variable list
pointers after they are deallocated and this fixes the problem for me although
I'm not totally sure it's the best way to fix this.
Lachlan
...
crash> extend /home/lmcilroy/bin/sial.so
Core LINUX_RELEASE == '2.6.18-238.12.1.el5'
< Sial interpreter version 3.0 >
Loading sial commands from /usr/share/sial/crash:/home/lmcilroy/.sial .... Done.
/home/lmcilroy/bin/sial.so: shared object loaded
crash> load very_long_directory_name/test.sial
crash> unload very_long_directory_name/test.sial
crash> load very_long_directory_name/test.sial
crash> unload very_long_directory_name/test.sial
crash> load very_long_directory_name/test.sial
crash> unload very_long_directory_name/test.sial
crash> load very_long_directory_name/test.sial
crash> unload very_long_directory_name/test.sial
Segmentation fault
Program received signal SIGSEGV, Segmentation fault.
sial_inivars (sv=0x2cf4488) at sial_var.c:549
549 if(!v->ini && v->dv && v->dv->init) {
Missing separate debuginfos, use: debuginfo-install crash-4.0.9-2.fc12.x86_64
(gdb) bt
#0 sial_inivars (sv=0x2cf4488) at sial_var.c:549
#1 0x00007fffed6b1d24 in sial_addsvs (type=1, sv=<value optimized out>) at
sial_var.c:821
#2 0x00007fffed69f07d in sial_execmcfunc (f=<value optimized out>, vp=<value
optimized out>) at sial_func.c:900
#3 0x00007fffed6a026b in sial_exefunc (fname=0x7fffffffdc90 "cciss_help",
vp=0x0) at sial_func.c:968
#4 0x00007fffed69cac2 in reg_callback (name=0x2c30538 "cciss", load=0) at
sial.c:922
#5 0x00007fffed69f72f in sial_docallback (fd=0x2f2ed58) at sial_func.c:264
#6 sial_freefile (fd=0x2f2ed58) at sial_func.c:288
#7 0x00007fffed69fe2a in sial_deletefile (name=0x7885a28
"very_long_directory_name/test.sial") at sial_func.c:314
#8 0x00007fffed6a5ce6 in sial_loadunload (load=0, name=<value optimized out>,
silent=0) at sial_api.c:1289
#9 0x00007fffed69c77d in unload_cmd () at sial.c:775
#10 0x000000000045d334 in exec_command () at main.c:740
#11 0x000000000045d57a in main_loop () at main.c:699
#12 0x0000000000554d19 in captured_command_loop (data=<value optimized out>) at
./main.c:228
#13 0x0000000000552feb in catch_errors (func=<value optimized out>,
func_args=<value optimized out>, errstring=<value optimized out>,
mask=<value optimized out>) at exceptions.c:531
#14 0x0000000000554a26 in captured_main (data=<value optimized out>) at
./main.c:958
#15 0x0000000000552feb in catch_errors (func=<value optimized out>,
func_args=<value optimized out>, errstring=<value optimized out>,
mask=<value optimized out>) at exceptions.c:531
#16 0x0000000000553be4 in gdb_main (args=0x2cf4488) at ./main.c:973
#17 0x0000000000553c1e in gdb_main_entry (argc=<value optimized out>, argv=<value
optimized out>) at ./main.c:993
#18 0x000000000045e0df in main (argc=<value optimized out>, argv=<value optimized
out>) at main.c:603
(gdb) p sv
$1 = (var_t *) 0x2cf4488
(gdb) p sv->next
$2 = (struct var_s *) 0x7463657269645f67
0x7463657269645f67 = "g-direct" which is part of the sial pathname (with the
underscore converted) so the memory has been reallocated.
diff -up crash-6.0.0/extensions/libsial/sial_func.c.orig
crash-6.0.0/extensions/libsial/sial_func.c
--- crash-6.0.0/extensions/libsial/sial_func.c.orig 2011-11-29 13:09:43.985631958 +1100
+++ crash-6.0.0/extensions/libsial/sial_func.c 2011-11-29 13:10:31.930603477 +1100
@@ -280,8 +280,14 @@ sial_freefile(fdata *fd)
}
/* free the associated static and global variables */
- if(fd->fsvs) sial_freesvs(fd->fsvs);
- if(fd->fgvs) sial_freesvs(fd->fgvs);
+ if(fd->fsvs) {
+ sial_freesvs(fd->fsvs);
+ fd->fsvs = NULL;
+ }
+ if(fd->fgvs) {
+ sial_freesvs(fd->fgvs);
+ fd->fgvs = NULL;
+ }
/* free all function nodes */
// let debugger know ...