aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c
blob: eb770f73d4a48923957576b5122da08c7074bed2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* { dg-additional-options "-fanalyzer-fine-grained" }
   -fanalyzer-fine-grained is currently required; see PR analyzer/107851.  */

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

/* Tests with symbolic buffer sizes.  */

void test_1 (int32_t n)
{
  int16_t *ptr = malloc (n * sizeof (int16_t));
  free (ptr);
}

void test_2 (int32_t n)
{
  int32_t *ptr = malloc (n * sizeof (int16_t)); /* { dg-line malloc2 } */
  free (ptr);

  /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } malloc2 } */
  /* { dg-message "'\[a-z0-9\\*\\(\\)\\s\]*' bytes" "note" { target *-*-* } malloc2 } */
  /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4" "note" { target *-*-* } malloc2 } */
}

void test_3 (int32_t n)
{
  void *ptr = malloc (n * sizeof (int16_t));
  int16_t *sptr = (int16_t *)ptr;
  free (sptr);
}

void test_4 (int32_t n)
{
  void *ptr = malloc (n * sizeof (int16_t)); /* { dg-message "'\[a-z0-9\\*\\(\\)\\s\]*'" "note" } */
  int32_t *iptr = (int32_t *)ptr; /* { dg-line assign4 } */
  free (iptr);

  /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } assign4 } */
  /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'" "note" { target *-*-* } assign4 } */
}

void test_5 (void)
{
  int32_t user_input;
  scanf("%i", &user_input);
  int32_t n;
  if (user_input == 0)
    n = 3 * user_input * sizeof (int16_t);
  else
    n = 5 * user_input * sizeof (int16_t);
  void *ptr = malloc (n);
  int16_t *sptr = (int16_t *)ptr;
  free (sptr);
}

void test_6 (void)
{
  int32_t user_input;
  scanf("%i", &user_input);
  int32_t n;
  if (user_input == 0)
    n = user_input;
  else if (user_input == 2)
    n = user_input * 3;
  else
    n = user_input * 5;
  /* n is an unknown_svalue at this point.  */
  void *ptr = malloc (n);
  int32_t *iptr = (int32_t *)ptr;
  free (iptr);
}

void *create_buffer(int32_t n)
{
  return malloc(n);
}

void test_7(int32_t n)
{
  int32_t *buf = create_buffer(n * sizeof (int32_t));
  free (buf);
}

void test_8(int32_t n)
{
  /* FIXME: At the moment, region_model::set_value (lhs, <return_value>)
     is called at the src_node of the return edge. This edge has no stmts
     associated with it, leading to a rejection of the warning inside
     impl_region_model_context::warn. To ensure that the indentation
     in the diagnostic is right, the warning has to be emitted on an EN
     that is after the return edge.  */
  int32_t *buf = create_buffer(n * sizeof(int16_t)); /* { dg-warning "" "" { xfail *-*-* } } */
  free (buf);
}

void test_9 (void)
{
  int32_t n;
  scanf("%i", &n);
  /* n is a conjured_svalue without any constraint. We have to assume
     that is a multiple of sizeof (int32_t *); see PR analyzer/110014.  */
  void *ptr = malloc (n);
  int32_t *iptr = (int32_t *)ptr;
  free (iptr);
}

void test_11 (void)
{
  int32_t n;
  scanf("%i", &n);
  void *ptr = malloc (n);
  if (n == sizeof (int32_t))
    {
      /* n is a conjured_svalue but guarded such that we
         know the value is a multiple of sizeof (*iptr).  */
      int32_t *iptr = (int32_t *)ptr;
      free (iptr);
    }
  else
    free (ptr);
}

void test_12 (void)
{
  int32_t n;
  scanf("%i", &n);
  void *ptr = malloc (n); /* { dg-message "'n' bytes" } */
  if (n == 5)
    {
      /* n is a conjured_svalue but guarded such that we
         know the value isn't a multiple of sizeof (*iptr).  */
      int32_t *iptr = (int32_t *)ptr; /* { dg-line assign12 } */
      free (iptr);
    }
  else
    free (ptr);
  /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } assign12 } */
  /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'" "note" { target *-*-* } assign12 } */
}

void test_13 (void)
{
  int32_t n;
  scanf("%i", &n);
  void *ptr = malloc (n);
  if (n == n * n)
    {
      /* n is a conjured_svalue but guarded such that we don't have an
         equivalence class for it. In such cases, we assume that the
         condition ensures that the value is okay.  */
      int32_t *iptr = (int32_t *)ptr;
      free (iptr);
    }
  else
    free (ptr);
}

int *test_14 (size_t n)
{
  int *ptr = NULL;
  /* n is an initial_svalue and guarded such that there is no equiv_class
     for n itself but only for a binop_svalue containing n.  */
  if (n % sizeof (int) == 0)
    ptr = malloc (n);
  return ptr;
}