File: data-model-5c.c

package info (click to toggle)
gcc-arm-none-eabi 15%3A14.2.rel1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,099,328 kB
  • sloc: cpp: 3,627,108; ansic: 2,571,498; ada: 834,230; f90: 235,082; makefile: 79,231; asm: 74,984; xml: 51,692; exp: 39,736; sh: 33,298; objc: 15,629; python: 15,069; fortran: 14,429; pascal: 7,003; awk: 5,070; perl: 3,106; ml: 285; lisp: 253; lex: 204; haskell: 135
file content (84 lines) | stat: -rw-r--r-- 1,840 bytes parent folder | download | duplicates (2)
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
/* A toy re-implementation of CPython's object model.  */

#include <stddef.h>
#include <string.h>
#include <stdlib.h>

typedef struct base_obj base_obj;
typedef struct type_obj type_obj;
typedef struct string_obj string_obj;

struct base_obj
{
  struct type_obj *ob_type;
  int ob_refcnt;
};

struct type_obj
{
  base_obj tp_base;
};

struct string_obj
{
  base_obj str_base;
  size_t str_len;
  char str_buf[];
};

type_obj type_type = {
  { &type_type, 1},
};

type_obj str_type = {
  { &str_type, 1},
};

base_obj *alloc_obj (type_obj *ob_type, size_t sz)
{
  base_obj *obj = (base_obj *)malloc (sz);
  if (!obj)
    return NULL;
  obj->ob_type = ob_type;
  obj->ob_refcnt = 1;
  return obj;
}

string_obj *new_string_obj (const char *str)
{
  //__analyzer_dump ();
  size_t len = strlen (str);
#if 1
  string_obj *str_obj
    = (string_obj *)alloc_obj (&str_type, sizeof (string_obj) + len + 1);
#else
  string_obj *str_obj = (string_obj *)malloc (sizeof (string_obj) + len + 1);
  if (!str_obj)
    return NULL;
  str_obj->str_base.ob_type = &str_type;
  str_obj->str_base.ob_refcnt = 1;
#endif
  str_obj->str_len = len; /* { dg-warning "dereference of NULL 'str_obj'" } */
  memcpy (str_obj->str_buf, str, len);
  str_obj->str_buf[len] = '\0';
  return str_obj;
}

void unref (string_obj *obj)
{
  if (--obj->str_base.ob_refcnt == 0)
    free (obj);
}

void test_1 (const char *str)
{
  string_obj *obj = new_string_obj (str);
  if (obj)
    unref (obj);
} /* { dg-bogus "leak" "" { xfail *-*-* } } */
/* XFAIL (false leak):
   Given that we only know "len" symbolically, this line:
     str_obj->str_buf[len] = '\0';
   is a symbolic write which could clobber the ob_type or ob_refcnt.
   It reports a leak when following the path where the refcount is clobbered
   to be a value that leads to the deallocator not being called.  */