Skip to content

Commit 719c083

Browse files
author
Dan Carpenter
committed
struct_assignment: re-work who zeroed/unknown buffers are assigned
Unrelated fix: In match_memdup() then I added some add_dereference(left/right) calls. Problem: This codes a tangled mess and zeroing memory does not work. This code is supposed to handle three things. #1 Copying a known struct to a different struct of the same type. #2 Copying unknown data to a struct. #3 Copying a zeroed buffer to a struct. I think #1 basically works. It's hard to get #2 wrong so I think that works but probably in the wrong way. But #3 was not working. In the original code, it treated "struct = struct" as different from memcpying. Which is sort of not a bad idea, but not how it's implemented. So get rid of that. Just say COPY_NORMAL. Use COPY_UNKNOWN for #2 of an unknown buffer and COPY_ZERO for a zeroed buffer. Signed-off-by: Dan Carpenter <[email protected]>
1 parent 83ffb38 commit 719c083

File tree

1 file changed

+58
-44
lines changed

1 file changed

+58
-44
lines changed

smatch_struct_assignment.c

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
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
*
@@ -62,8 +66,8 @@
6266

6367
enum {
6468
COPY_NORMAL,
65-
COPY_MEMCPY,
66-
COPY_MEMSET,
69+
COPY_UNKNOWN,
70+
COPY_ZERO,
6771
};
6872

6973
static 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

449445
static 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

461462
static 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

472479
static 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

489503
static 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

497511
static 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

569583
void register_struct_assignment(int id)

0 commit comments

Comments
 (0)