4545 *
4646 * p1->x->y->z->one->two->three = p2->x->y->z->one->two->three;
4747 *
48+ * We probably want to distinguish between between shallow and deep copies so
49+ * that if we memset(p1, 0, sizeof(*p1)) then it just sets p1->x to zero and not
50+ * p1->x->y.
51+ *
4852 * I don't have a proper solution for this problem right now. I just copy one
4953 * level and don't nest. It should handle limitted nesting but intelligently.
5054 *
6266
6367enum {
6468 COPY_NORMAL ,
65- COPY_MEMCPY ,
66- COPY_MEMSET ,
69+ COPY_UNKNOWN ,
70+ COPY_ZERO ,
6771};
6872
6973static struct symbol * get_struct_type (struct expression * expr )
@@ -190,7 +194,7 @@ static void set_inner_struct_members(int mode, struct expression *faked, struct
190194
191195 if (member -> ident ) {
192196 left = member_expression (left , '.' , member -> ident );
193- if (mode != COPY_MEMSET && right )
197+ if (mode == COPY_NORMAL && right )
194198 right = member_expression (right , '.' , member -> ident );
195199 }
196200
@@ -212,18 +216,13 @@ static void set_inner_struct_members(int mode, struct expression *faked, struct
212216
213217 left_member = member_expression (left , '.' , tmp -> ident );
214218
215- switch (mode ) {
216- case COPY_NORMAL :
217- case COPY_MEMCPY :
218- if (right )
219- right_expr = member_expression (right , '.' , tmp -> ident );
220- else
221- right_expr = unknown_value_expression (left_member );
222- break ;
223- case COPY_MEMSET :
224- right_expr = right ;
225- break ;
226- }
219+ right_expr = NULL ;
220+ if (mode == COPY_NORMAL && right )
221+ right_expr = member_expression (right , '.' , tmp -> ident );
222+ if (mode == COPY_ZERO )
223+ right_expr = zero_expr ();
224+ if (!right_expr )
225+ right_expr = unknown_value_expression (left_member );
227226
228227 assign = assign_expression (left_member , '=' , right_expr );
229228 split_fake_expr (assign );
@@ -260,7 +259,7 @@ static void __struct_members_copy(int mode, struct expression *faked,
260259 goto done ;
261260 }
262261
263- if (mode != COPY_MEMSET )
262+ if (mode == COPY_NORMAL )
264263 right = get_right_base_expr (struct_type , right );
265264
266265 FOR_EACH_PTR (struct_type -> symbol_list , tmp ) {
@@ -281,22 +280,13 @@ static void __struct_members_copy(int mode, struct expression *faked,
281280 left_member = member_expression (left , '.' , tmp -> ident );
282281 right_expr = NULL ;
283282
284- switch (mode ) {
285- case COPY_NORMAL :
286- case COPY_MEMCPY :
287- if (right )
288- right_expr = member_expression (right , '.' , tmp -> ident );
289- else
290- right_expr = unknown_value_expression (left_member );
291- break ;
292- case COPY_MEMSET :
293- right_expr = right ;
294- break ;
295- }
296- if (!right_expr ) {
297- sm_perror ("No right member" );
298- continue ;
299- }
283+ if (mode == COPY_NORMAL && right )
284+ right_expr = member_expression (right , '.' , tmp -> ident );
285+ if (mode == COPY_ZERO )
286+ right_expr = zero_expr ();
287+ if (!right_expr )
288+ right_expr = unknown_value_expression (left_member );
289+
300290 assign = assign_expression (left_member , '=' , right_expr );
301291 split_fake_expr (assign );
302292 } END_FOR_EACH_PTR (tmp );
@@ -416,6 +406,7 @@ void __fake_struct_member_assignments(struct expression *expr)
416406{
417407 struct expression * left , * right ;
418408 struct symbol * type ;
409+ int mode ;
419410
420411 if (expr -> op != '=' )
421412 return ;
@@ -435,44 +426,61 @@ void __fake_struct_member_assignments(struct expression *expr)
435426 left = expr -> left ;
436427 right = expr -> right ;
437428
438- if (returns_zeroed_mem (expr -> right ))
439- right = zero_expr ();
440- else if (type -> type == SYM_PTR ) {
429+ if (type -> type == SYM_PTR ) {
441430 /* Convert "p = q;" to "*p = *q;" */
442431 left = add_dereference (left );
443432 right = add_dereference (right );
444433 }
445434
446- __struct_members_copy (COPY_NORMAL , expr , left , right );
435+ if (returns_zeroed_mem (expr -> right ))
436+ mode = COPY_ZERO ;
437+ else if (types_equiv (get_type (left ), get_type (right )))
438+ mode = COPY_NORMAL ;
439+ else
440+ mode = COPY_UNKNOWN ;
441+
442+ __struct_members_copy (mode , expr , left , right );
447443}
448444
449445static void match_memset (const char * fn , struct expression * expr , void * _size_arg )
450446{
451447 struct expression * buf ;
452448 struct expression * val ;
449+ int mode ;
453450
454451 buf = get_argument_from_call_expr (expr -> args , 0 );
455452 val = get_argument_from_call_expr (expr -> args , 1 );
456453
457454 buf = strip_expr (buf );
458- __struct_members_copy (COPY_MEMSET , expr , add_dereference (buf ), val );
455+ if (expr_is_zero (val ))
456+ mode = COPY_ZERO ;
457+ else
458+ mode = COPY_UNKNOWN ;
459+ __struct_members_copy (mode , expr , add_dereference (buf ), NULL );
459460}
460461
461462static void match_memcpy (const char * fn , struct expression * expr , void * _arg )
462463{
463464 struct expression * dest ;
464465 struct expression * src ;
466+ int mode ;
465467
466468 dest = get_argument_from_call_expr (expr -> args , 0 );
467469 src = get_argument_from_call_expr (expr -> args , 1 );
468470
469- __struct_members_copy (COPY_MEMCPY , expr , add_dereference (dest ), add_dereference (src ));
471+ if (types_equiv (get_type (src ), get_type (dest )))
472+ mode = COPY_NORMAL ;
473+ else
474+ mode = COPY_UNKNOWN ;
475+
476+ __struct_members_copy (mode , expr , add_dereference (dest ), add_dereference (src ));
470477}
471478
472479static void match_memdup (const char * fn , struct expression * call_expr ,
473480 struct expression * expr , void * _unused )
474481{
475482 struct expression * left , * right , * arg ;
483+ int mode ;
476484
477485 if (!expr || expr -> type != EXPR_ASSIGNMENT )
478486 return ;
@@ -483,15 +491,21 @@ static void match_memdup(const char *fn, struct expression *call_expr,
483491 if (right -> type != EXPR_CALL )
484492 return ;
485493 arg = get_argument_from_call_expr (right -> args , 0 );
486- __struct_members_copy (COPY_MEMCPY , expr , left , arg );
494+
495+ if (types_equiv (get_type (left ), get_type (right )))
496+ mode = COPY_NORMAL ;
497+ else
498+ mode = COPY_UNKNOWN ;
499+
500+ __struct_members_copy (mode , expr , add_dereference (left ), add_dereference (arg ));
487501}
488502
489503static void match_memcpy_unknown (const char * fn , struct expression * expr , void * _arg )
490504{
491505 struct expression * dest ;
492506
493507 dest = get_argument_from_call_expr (expr -> args , 0 );
494- __struct_members_copy (COPY_MEMCPY , expr , add_dereference (dest ), NULL );
508+ __struct_members_copy (COPY_UNKNOWN , expr , add_dereference (dest ), NULL );
495509}
496510
497511static void match_sscanf (const char * fn , struct expression * expr , void * unused )
@@ -503,7 +517,7 @@ static void match_sscanf(const char *fn, struct expression *expr, void *unused)
503517 FOR_EACH_PTR (expr -> args , arg ) {
504518 if (++ i < 2 )
505519 continue ;
506- __struct_members_copy (COPY_MEMCPY , expr , add_dereference (arg ), NULL );
520+ __struct_members_copy (COPY_UNKNOWN , expr , add_dereference (arg ), NULL );
507521 } END_FOR_EACH_PTR (arg );
508522}
509523
@@ -516,7 +530,7 @@ static void unop_expr(struct expression *expr)
516530 if (!is_pointer (expr ))
517531 return ;
518532 faked_expression = expr ;
519- __struct_members_copy (COPY_MEMCPY , expr , expr -> unop , NULL );
533+ __struct_members_copy (COPY_UNKNOWN , expr , expr -> unop , NULL );
520534 faked_expression = NULL ;
521535}
522536
@@ -561,9 +575,9 @@ static void db_param_cleared(struct expression *expr, int param, char *key, char
561575 return ;
562576
563577 if (strcmp (value , "0" ) == 0 )
564- __struct_members_copy (COPY_MEMSET , expr , add_dereference (arg ), zero_expr () );
578+ __struct_members_copy (COPY_ZERO , expr , add_dereference (arg ), NULL );
565579 else
566- __struct_members_copy (COPY_MEMCPY , expr , add_dereference (arg ), NULL );
580+ __struct_members_copy (COPY_UNKNOWN , expr , add_dereference (arg ), NULL );
567581}
568582
569583void register_struct_assignment (int id )
0 commit comments