Hi, One of our big application segv in libgcc code while unwinding the stack.
This is a random crash while the application throws a c++ exception and unwinds the stack. Incidents are random and never can be reproduced by any test case. The libgcc that is used is based on GCC 8. Fortunately, we got some information through the stack trace, and narrowed down the crash is in the routine "init_object" of libgcc/unwind-dw2-pde.c: 777 count = classify_object_over_fdes (ob, ob->u.single); when loading the 2nd parameter of the call to "classify_object_over_fdes". i.e, the address that is pointed by "ob->u.single" is invalid. And the outer caller we can track back is the following line 1066 of the routine "_Unwind_Find_FDE": 1060 /* Classify and search the objects we've not yet processed. */ 1061 while ((ob = unseen_objects)) 1062 { 1063 struct object **p; 1064 1065 unseen_objects = ob->next; 1066 f = search_object (ob, pc); Then we suspected that the construction of the static variable "unseen_objects" might have some bug. Then after studying the source code that constructs "unseen_objects" in libgcc/unwind-dw2-pde.c, I found an issue in the routines "__register_frame" and "__register_frame_table" as following: 127 void 128 __register_frame (void *begin) 129 { 130 struct object *ob; 131 132 /* If .eh_frame is empty, don't register at all. */ 133 if (*(uword *) begin == 0) 134 return; 135 136 ob = malloc (sizeof (struct object)); 137 __register_frame_info (begin, ob); 138 } 181 void 182 __register_frame_table (void *begin) 183 { 184 struct object *ob = malloc (sizeof (struct object)); 185 __register_frame_info_table (begin, ob); 186 } 187 In the above, one obvious issue in the source code is at line 136, line 137, and line 184 and line 185: the return value of call to "malloc" is not checked against NULL before it was passed as the second parameter of the follwoing call. This might cause unpredicted random behavior. I checked the latest trunk GCC libgcc, the same issue is there too. This patch is for the latest trunk GCC. Please let me know any comments on this? thanks. Qing ======================= Fix two issues in libgcc/unwind-dw2-fde.c: A. The returned value of call to malloc is not checked against NULL. This might cause unpredicted behavior during stack unwinding. B. Check for null begin parameter (as well as pointer to null) in __register_frame_info_table_bases and __register_frame_table. libgcc/ChangeLog: * unwind-dw2-fde.c (__register_frame): Check the return value of call to malloc. (__register_frame_info_table_bases): Check for null begin parameter. (__register_frame_table): Check the return value of call to malloc, Check for null begin parameter. --- libgcc/unwind-dw2-fde.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c index cdfd3974c99..f0bc29d682a 100644 --- a/libgcc/unwind-dw2-fde.c +++ b/libgcc/unwind-dw2-fde.c @@ -169,6 +169,8 @@ __register_frame (void *begin) return; ob = malloc (sizeof (struct object)); + if (ob == NULL) + abort (); __register_frame_info (begin, ob); } @@ -180,6 +182,10 @@ void __register_frame_info_table_bases (void *begin, struct object *ob, void *tbase, void *dbase) { + /* If .eh_frame is empty, don't register at all. */ + if ((const uword *) begin == 0 || *(const uword *) begin == 0) + return; + ob->pc_begin = (void *)-1; ob->tbase = tbase; ob->dbase = dbase; @@ -210,7 +216,13 @@ __register_frame_info_table (void *begin, struct object *ob) void __register_frame_table (void *begin) { + /* If .eh_frame is empty, don't register at all. */ + if (*(uword *) begin == 0) + return; + struct object *ob = malloc (sizeof (struct object)); + if (ob == NULL) + abort (); __register_frame_info_table (begin, ob); } -- 2.31.1