Bug Summary

File:builds/wireshark/wireshark/epan/wslua/lrexlib/common.c
Warning:line 181, column 5
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name common.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /usr/include/lua5.4 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D PCRE2_CODE_UNIT_WIDTH=8 -D VERSION="2.9.2" -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D PCRE2_CODE_UNIT_WIDTH=8 -D VERSION="2.9.2" -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /usr/include/lua5.4 -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIC /builds/wireshark/wireshark/epan/wslua/lrexlib/common.c -o /builds/wireshark/wireshark/sbout/2024-11-18-100252-3912-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-11-18-100252-3912-1 -x c /builds/wireshark/wireshark/epan/wslua/lrexlib/common.c
1/* common.c */
2/* See Copyright Notice in the file LICENSE */
3/* SPDX-License-Identifier: MIT */
4
5#include <wireshark.h>
6DIAG_OFF_CLANG(shorten-64-to-32)clang diagnostic push clang diagnostic ignored "-Wshorten-64-to-32"
7#ifdef _MSC_VER
8/* disable: " warning C4244: '=': conversion from 'lua _Integer' to 'int',
9 * possible loss of data" */
10#pragma warning(disable:4244)
11/* warning C4267: '+=': conversion from 'size_t' to 'int',
12 * possible loss of data */
13#pragma warning(disable:4267)
14#endif
15
16#include <stdlib.h>
17#include <ctype.h>
18#include <string.h>
19#include "lua.h"
20#include "lauxlib.h"
21#include "common.h"
22
23#define N_ALIGNsizeof(int) sizeof(int)
24
25/* the table must be on Lua stack top */
26int get_int_field (lua_State *L, const char* field)
27{
28 int val;
29 lua_getfield (L, -1, field);
30 val = lua_tointeger (L, -1)lua_tointegerx(L,(-1),((void*)0));
31 lua_pop (L, 1)lua_settop(L, -(1)-1);
32 return val;
33}
34
35/* the table must be on Lua stack top */
36void set_int_field (lua_State *L, const char* field, int val)
37{
38 lua_pushinteger (L, val);
39 lua_setfield (L, -2, field);
40}
41
42void *Lmalloc(lua_State *L, size_t size) {
43 void *ud;
44 lua_Alloc lalloc = lua_getallocf(L, &ud);
45 return lalloc(ud, NULL((void*)0), 0, size);
46}
47
48void *Lrealloc(lua_State *L, void *p, size_t osize, size_t nsize) {
49 void *ud;
50 lua_Alloc lalloc = lua_getallocf(L, &ud);
51 return lalloc(ud, p, osize, nsize);
52}
53
54void Lfree(lua_State *L, void *p, size_t osize) {
55 void *ud;
56 lua_Alloc lalloc = lua_getallocf(L, &ud);
57 lalloc(ud, p, osize, 0);
58}
59
60/* This function fills a table with string-number pairs.
61 The table can be passed as the 1-st lua-function parameter,
62 otherwise it is created. The return value is the filled table.
63*/
64int get_flags (lua_State *L, const flag_pair **arrs) {
65 const flag_pair *p;
66 const flag_pair **pp;
67 int nparams = lua_gettop(L);
68
69 if(nparams == 0)
70 lua_newtable(L)lua_createtable(L, 0, 0);
71 else {
72 if(!lua_istable(L, 1)(lua_type(L, (1)) == 5))
73 luaL_argerror(L, 1, "not a table");
74 if(nparams > 1)
75 lua_pushvalue(L, 1);
76 }
77
78 for(pp=arrs; *pp; ++pp) {
79 for(p=*pp; p->key; ++p) {
80 lua_pushstring(L, p->key);
81 lua_pushinteger(L, p->val);
82 lua_rawset(L, -3);
83 }
84 }
85 return 1;
86}
87
88const char *get_flag_key (const flag_pair *fp, int val) {
89 for (; fp->key; ++fp) {
90 if (fp->val == val)
91 return fp->key;
92 }
93 return NULL((void*)0);
94}
95
96/* Classes */
97
98/*
99 * class TFreeList
100 * ***************
101 * Simple array of pointers to TBuffer's.
102 * The array has fixed capacity (not expanded automatically).
103 */
104
105void freelist_init (TFreeList *fl) {
106 fl->top = 0;
107}
108
109void freelist_add (TFreeList *fl, TBuffer *buf) {
110 fl->list[fl->top++] = buf;
111}
112
113void freelist_free (TFreeList *fl) {
114 while (fl->top > 0)
115 buffer_free (fl->list[--fl->top]);
116}
117
118/*
119 * class TBuffer
120 * *************
121 * Auto-extensible array of characters for building long strings incrementally.
122 * * Differs from luaL_Buffer in that:
123 * * its operations do not change Lua stack top position
124 * * buffer_addvalue does not extract the value from Lua stack
125 * * buffer_pushresult does not have to be the last operation
126 * * Uses TFreeList class:
127 * * for inserting itself into a TFreeList instance for future clean-up
128 * * calls freelist_free prior to calling luaL_error.
129 * * Has specialized "Z-operations" for maintaining mixed string/integer
130 * array: bufferZ_addlstring, bufferZ_addnum and bufferZ_next.
131 * * if the array is intended to be "mixed", then the methods
132 * buffer_addlstring and buffer_addvalue must not be used
133 * (the application will crash on bufferZ_next).
134 * * conversely, if the array is not intended to be "mixed",
135 * then the method bufferZ_next must not be used.
136 */
137
138enum { ID_NUMBER, ID_STRING };
139
140void buffer_init (TBuffer *buf, size_t sz, lua_State *L, TFreeList *fl) {
141 buf->arr = (char*) Lmalloc(L, sz);
142 if (!buf->arr) {
143 freelist_free (fl);
144 luaL_error (L, "malloc failed");
145 }
146 buf->size = sz;
147 buf->top = 0;
148 buf->L = L;
149 buf->freelist = fl;
150 freelist_add (fl, buf);
151}
152
153void buffer_free (TBuffer *buf) {
154 Lfree(buf->L, buf->arr, buf->size);
155}
156
157void buffer_clear (TBuffer *buf) {
158 buf->top = 0;
159}
160
161void buffer_pushresult (TBuffer *buf) {
162 lua_pushlstring (buf->L, buf->arr, buf->top);
163}
164
165void buffer_addbuffer (TBuffer *trg, TBuffer *src) {
166 buffer_addlstring (trg, src->arr, src->top);
167}
168
169void buffer_addlstring (TBuffer *buf, const void *src, size_t sz) {
170 size_t newtop = buf->top + sz;
171 if (newtop > buf->size) {
2
Assuming 'newtop' is > field 'size'
3
Taking true branch
172 char *p = (char*) Lrealloc (buf->L, buf->arr, buf->size, 2 * newtop); /* 2x expansion */
4
'p' initialized here
173 if (!p) {
5
Assuming 'p' is null
6
Taking true branch
174 freelist_free (buf->freelist);
175 luaL_error (buf->L, "realloc failed");
176 }
177 buf->arr = p;
7
Null pointer value stored to field 'arr'
178 buf->size = 2 * newtop;
179 }
180 if (src)
8
Assuming 'src' is non-null
9
Taking true branch
181 memcpy (buf->arr + buf->top, src, sz);
10
Null pointer passed to 1st parameter expecting 'nonnull'
182 buf->top = newtop;
183}
184
185void buffer_addvalue (TBuffer *buf, int stackpos) {
186 size_t len;
187 const char *p = lua_tolstring (buf->L, stackpos, &len);
188 buffer_addlstring (buf, p, len);
1
Calling 'buffer_addlstring'
189}
190
191void bufferZ_addlstring (TBuffer *buf, const void *src, size_t len) {
192 int n;
193 size_t header[2] = { ID_STRING };
194 header[1] = len;
195 buffer_addlstring (buf, header, sizeof (header));
196 buffer_addlstring (buf, src, len);
197 n = len % N_ALIGNsizeof(int);
198 if (n) buffer_addlstring (buf, NULL((void*)0), N_ALIGNsizeof(int) - n);
199}
200
201void bufferZ_addnum (TBuffer *buf, size_t num) {
202 size_t header[2] = { ID_NUMBER };
203 header[1] = num;
204 buffer_addlstring (buf, header, sizeof (header));
205}
206
207/* 1. When called repeatedly on the same TBuffer, its existing data
208 is discarded and overwritten by the new data.
209 2. The TBuffer's array is never shrunk by this function.
210*/
211void bufferZ_putrepstring (TBuffer *BufRep, int reppos, int nsub) {
212 char dbuf[] = { 0, 0 };
213 size_t replen;
214 const char *p = lua_tolstring (BufRep->L, reppos, &replen);
215 const char *end = p + replen;
216 BufRep->top = 0;
217 while (p < end) {
218 const char *q;
219 for (q = p; q < end && *q != '%'; ++q)
220 {}
221 if (q != p)
222 bufferZ_addlstring (BufRep, p, q - p);
223 if (q < end) {
224 if (++q < end) { /* skip % */
225 if (g_ascii_isdigit (*q)((g_ascii_table[(guchar) (*q)] & G_ASCII_DIGIT) != 0)) {
226 int num;
227 *dbuf = *q;
228 num = strtol (dbuf, NULL((void*)0), 10);
229 if (num == 1 && nsub == 0)
230 num = 0;
231 else if (num > nsub) {
232 freelist_free (BufRep->freelist);
233 luaL_error (BufRep->L, "invalid capture index");
234 }
235 bufferZ_addnum (BufRep, num);
236 }
237 else bufferZ_addlstring (BufRep, q, 1);
238 }
239 p = q + 1;
240 }
241 else break;
242 }
243}
244
245/******************************************************************************
246 The intended use of this function is as follows:
247 size_t iter = 0;
248 while (bufferZ_next (buf, &iter, &num, &str)) {
249 if (str) do_something_with_string (str, num);
250 else do_something_with_number (num);
251 }
252*******************************************************************************
253*/
254int bufferZ_next (TBuffer *buf, size_t *iter, size_t *num, const char **str) {
255 if (*iter < buf->top) {
256 size_t *ptr_header = (size_t*)(buf->arr + *iter);
257 *num = ptr_header[1];
258 *iter += 2 * sizeof (size_t);
259 *str = NULL((void*)0);
260 if (*ptr_header == ID_STRING) {
261 int n;
262 *str = buf->arr + *iter;
263 *iter += *num;
264 n = *iter % N_ALIGNsizeof(int);
265 if (n) *iter += (N_ALIGNsizeof(int) - n);
266 }
267 return 1;
268 }
269 return 0;
270}
271
272#if LUA_VERSION_NUM504 > 501
273int luaL_typerror (lua_State *L, int narg, const char *tname) {
274 const char *msg = lua_pushfstring(L, "%s expected, got %s",
275 tname, luaL_typename(L, narg)lua_typename(L, lua_type(L,(narg))));
276 return luaL_argerror(L, narg, msg);
277}
278#endif
279
280#ifndef REX_NOEMBEDDEDTEST
281static int ud_topointer (lua_State *L) {
282 lua_pushlightuserdata (L, lua_touserdata (L, 1));
283 return 1;
284}
285
286static int ud_len (lua_State *L) {
287 lua_pushinteger (L, lua_objlenlua_rawlen (L, 1));
288 return 1;
289}
290
291/* for testing purposes only */
292int newmembuffer (lua_State *L) {
293 size_t len;
294 const char* s = luaL_checklstring (L, 1, &len);
295 void *ud = lua_newuserdata (L, len)lua_newuserdatauv(L,len,1);
296 memcpy (ud, s, len);
297 lua_newtable (L)lua_createtable(L, 0, 0); /* metatable */
298 lua_pushvalue (L, -1);
299 lua_setfield (L, -2, "__index"); /* metatable.__index = metatable */
300 lua_pushcfunction (L, ud_topointer)lua_pushcclosure(L, (ud_topointer), 0);
301 lua_setfield (L, -2, "topointer");
302 lua_pushcfunction (L, ud_len)lua_pushcclosure(L, (ud_len), 0);
303 lua_setfield (L, -2, "__len");
304 lua_setmetatable (L, -2);
305 return 1;
306}
307#endif /* #ifndef REX_NOEMBEDDEDTEST */