Coverage Report

Created: 2026-01-17 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dropbear/src/dbmalloc.c
Line
Count
Source
1
#include "dbmalloc.h"
2
#include "dbutil.h"
3
4
5
3.64M
void * m_calloc(size_t nmemb, size_t size) {
6
3.64M
    if (SIZE_T_MAX / nmemb < size) {
7
0
        dropbear_exit("m_calloc failed");
8
0
    }
9
3.64M
    return m_malloc(nmemb*size);
10
3.64M
}
11
12
11.0k
void * m_strdup(const char * str) {
13
11.0k
    char* ret;
14
11.0k
    unsigned int len;
15
11.0k
    len = strlen(str);
16
17
11.0k
    ret = m_malloc(len+1);
18
11.0k
    if (ret == NULL) {
19
0
        dropbear_exit("m_strdup failed");
20
0
    }
21
11.0k
    memcpy(ret, str, len+1);
22
11.0k
    return ret;
23
11.0k
}
24
25
#if !DROPBEAR_TRACKING_MALLOC
26
27
/* Simple wrappers around malloc etc */
28
void * m_malloc(size_t size) {
29
30
  void* ret;
31
32
  if (size == 0) {
33
    dropbear_exit("m_malloc failed");
34
  }
35
  ret = calloc(1, size);
36
  if (ret == NULL) {
37
    dropbear_exit("m_malloc failed");
38
  }
39
  return ret;
40
41
}
42
43
void * m_realloc(void* ptr, size_t size) {
44
45
  void *ret;
46
47
  if (size == 0) {
48
    dropbear_exit("m_realloc failed");
49
  }
50
  ret = realloc(ptr, size);
51
  if (ret == NULL) {
52
    dropbear_exit("m_realloc failed");
53
  }
54
  return ret;
55
}
56
57
58
#else
59
60
/* For fuzzing */
61
62
struct dbmalloc_header {
63
    unsigned int epoch;
64
    struct dbmalloc_header *prev;
65
    struct dbmalloc_header *next;
66
};
67
68
static void put_alloc(struct dbmalloc_header *header);
69
static void remove_alloc(struct dbmalloc_header *header);
70
71
/* end of the linked list */
72
static struct dbmalloc_header* staple;
73
74
unsigned int current_epoch = 0;
75
76
3.51k
void m_malloc_set_epoch(unsigned int epoch) {
77
3.51k
    current_epoch = epoch;
78
3.51k
}
79
80
3.51k
void m_malloc_free_epoch(unsigned int epoch, int dofree) {
81
3.51k
    struct dbmalloc_header* header;
82
3.51k
    struct dbmalloc_header* nextheader = NULL;
83
3.51k
    struct dbmalloc_header* oldstaple = staple;
84
3.51k
    staple = NULL;
85
    /* free allocations from this epoch, create a new staple-anchored list from
86
    the remainder */
87
3.66M
    for (header = oldstaple; header; header = nextheader)
88
3.65M
    {
89
3.65M
        nextheader = header->next;
90
3.65M
        if (header->epoch == epoch) {
91
4.14k
            if (dofree) {
92
4.14k
                free(header);
93
4.14k
            }
94
3.65M
        } else {
95
3.65M
            header->prev = NULL;
96
3.65M
            header->next = NULL;
97
3.65M
            put_alloc(header);
98
3.65M
        }
99
3.65M
    }
100
3.51k
}
101
102
9.36M
static void put_alloc(struct dbmalloc_header *header) {
103
9.36M
    assert(header->next == NULL);
104
9.36M
    assert(header->prev == NULL);
105
9.36M
    if (staple) {
106
9.36M
        staple->prev = header;
107
9.36M
    }
108
9.36M
    header->next = staple;
109
9.36M
    staple = header;
110
9.36M
}
111
112
5.70M
static void remove_alloc(struct dbmalloc_header *header) {
113
5.70M
    if (header->prev) {
114
4.62M
        header->prev->next = header->next;
115
4.62M
    }
116
5.70M
    if (header->next) {
117
5.70M
        header->next->prev = header->prev;
118
5.70M
    }
119
5.70M
    if (staple == header) {
120
1.08M
        staple = header->next;
121
1.08M
    }
122
5.70M
    header->prev = NULL;
123
5.70M
    header->next = NULL;
124
5.70M
}
125
126
5.70M
static struct dbmalloc_header* get_header(void* ptr) {
127
5.70M
    char* bptr = ptr;
128
5.70M
    return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)];
129
5.70M
}
130
131
4.03M
void * m_malloc(size_t size) {
132
4.03M
    char* mem = NULL;
133
4.03M
    struct dbmalloc_header* header = NULL;
134
135
4.03M
    if (size == 0 || size > 1e9) {
136
0
        dropbear_exit("m_malloc failed");
137
0
    }
138
139
4.03M
    size = size + sizeof(struct dbmalloc_header);
140
141
4.03M
    mem = calloc(1, size);
142
4.03M
    if (mem == NULL) {
143
0
        dropbear_exit("m_malloc failed");
144
0
    }
145
4.03M
    header = (struct dbmalloc_header*)mem;
146
4.03M
    put_alloc(header);
147
4.03M
    header->epoch = current_epoch;
148
4.03M
    return &mem[sizeof(struct dbmalloc_header)];
149
4.03M
}
150
151
1.68M
void * m_realloc(void* ptr, size_t size) {
152
1.68M
    char* mem = NULL;
153
1.68M
    struct dbmalloc_header* header = NULL;
154
1.68M
    if (size == 0 || size > 1e9) {
155
0
        dropbear_exit("m_realloc failed");
156
0
    }
157
158
1.68M
    header = get_header(ptr);
159
1.68M
    remove_alloc(header);
160
161
1.68M
    size = size + sizeof(struct dbmalloc_header);
162
1.68M
    mem = realloc(header, size);
163
1.68M
    if (mem == NULL) {
164
0
        dropbear_exit("m_realloc failed");
165
0
    }
166
167
1.68M
    header = (struct dbmalloc_header*)mem;
168
1.68M
    put_alloc(header);
169
1.68M
    return &mem[sizeof(struct dbmalloc_header)];
170
1.68M
}
171
172
4.04M
void m_free_direct(void* ptr) {
173
4.04M
    struct dbmalloc_header* header = NULL;
174
4.04M
    if (!ptr) {
175
21.6k
        return;
176
21.6k
    }
177
4.02M
    header = get_header(ptr);
178
4.02M
    remove_alloc(header);
179
4.02M
    free(header);
180
4.02M
}
181
182
#endif /* DROPBEAR_TRACKING_MALLOC */
183
184
1.67M
void * m_realloc_ltm(void* ptr, size_t oldsize, size_t newsize) {
185
1.67M
   (void)oldsize;
186
1.67M
   return m_realloc(ptr, newsize);
187
1.67M
}
188
189
2.69M
void m_free_ltm(void *mem, size_t size) {
190
2.69M
   (void)size;
191
2.69M
   m_free_direct(mem);
192
2.69M
}