Bug Summary

File:builds/wireshark/wireshark/epan/wslua/wslua_tree.c
Warning:line 742, column 5
Undefined or garbage value returned to caller

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 wslua_tree.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-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/lua5.4 -isystem /builds/wireshark/wireshark/build/epan/wslua -isystem /builds/wireshark/wireshark/epan/wslua -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -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-21/lib/clang/21/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-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -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 -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-03-11-100403-3621-1 -x c /builds/wireshark/wireshark/epan/wslua/wslua_tree.c
1/*
2 * wslua_tree.c
3 *
4 * Wireshark's interface to the Lua Programming Language
5 *
6 * (c) 2006, Luis E. Garcia Ontanon <[email protected]>
7 * (c) 2008, Balint Reczey <[email protected]>
8 *
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <[email protected]>
11 * Copyright 1998 Gerald Combs
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 */
15
16#include "config.h"
17
18/* WSLUA_MODULE Tree Adding Information To The Dissection Tree */
19
20#include "wslua.h"
21#include <epan/exceptions.h>
22#include <epan/show_exception.h>
23
24static int wslua_ett = -1;
25
26static GPtrArray* outstanding_TreeItem;
27
28
29/* pushing a TreeItem with a NULL item or subtree is completely valid for this function */
30TreeItem push_TreeItem(lua_State *L, proto_tree *tree, proto_item *item) {
31 TreeItem ti = g_new(struct _wslua_treeitem, 1)((struct _wslua_treeitem *) g_malloc_n ((1), sizeof (struct _wslua_treeitem
)))
;
32
33 ti->tree = tree;
34 ti->item = item;
35 ti->expired = false0;
36
37 g_ptr_array_add(outstanding_TreeItem, ti);
38
39 return *(pushTreeItem(L,ti));
40}
41
42/* creates the TreeItem but does NOT push it into Lua */
43TreeItem create_TreeItem(proto_tree* tree, proto_item* item)
44{
45 TreeItem tree_item = (TreeItem)g_malloc(sizeof(struct _wslua_treeitem));
46 tree_item->tree = tree;
47 tree_item->item = item;
48 tree_item->expired = false0;
49
50 return tree_item;
51}
52
53CLEAR_OUTSTANDING(TreeItem, expired, true)void clear_outstanding_TreeItem(void) { while (outstanding_TreeItem
->len) { TreeItem p = (TreeItem)g_ptr_array_remove_index_fast
(outstanding_TreeItem,0); if (p) { if (p->expired != 1) p->
expired = 1; else g_free(p); } } }
54
55WSLUA_CLASS_DEFINE(TreeItem,FAIL_ON_NULL_OR_EXPIRED("TreeItem"))TreeItem toTreeItem(lua_State* L, int idx) { TreeItem* v = (TreeItem
*)lua_touserdata (L, idx); if (!v) luaL_error(L, "bad argument %d (%s expected, got %s)"
, idx, "TreeItem", lua_typename(L, lua_type(L, idx))); return
v ? *v : ((void*)0); } TreeItem checkTreeItem(lua_State* L, int
idx) { TreeItem* p; luaL_checktype(L,idx,7); p = (TreeItem*)
luaL_checkudata(L, idx, "TreeItem"); if (!*p) { luaL_argerror
(L,idx,"null " "TreeItem"); } else if ((*p)->expired) { luaL_argerror
(L,idx,"expired " "TreeItem"); }; return p ? *p : ((void*)0);
} TreeItem* pushTreeItem(lua_State* L, TreeItem v) { TreeItem
* p; luaL_checkstack(L,2,"Unable to grow stack\n"); p = (TreeItem
*)lua_newuserdatauv(L,sizeof(TreeItem),1); *p = v; (lua_getfield
(L, (-1000000 - 1000), ("TreeItem"))); lua_setmetatable(L, -2
); return p; }_Bool isTreeItem(lua_State* L,int i) { void *p;
if(!lua_isuserdata(L,i)) return 0; p = lua_touserdata(L, i);
lua_getfield(L, (-1000000 - 1000), "TreeItem"); if (p == ((void
*)0) || !lua_getmetatable(L, i) || !lua_rawequal(L, -1, -2)) p
=((void*)0); lua_settop(L, -(2)-1); return p ? 1 : 0; } TreeItem
shiftTreeItem(lua_State* L,int i) { TreeItem* p; if(!lua_isuserdata
(L,i)) return ((void*)0); p = (TreeItem*)lua_touserdata(L, i)
; lua_getfield(L, (-1000000 - 1000), "TreeItem"); if (p == ((
void*)0) || !lua_getmetatable(L, i) || !lua_rawequal(L, -1, -
2)) p=((void*)0); lua_settop(L, -(2)-1); if (p) { (lua_rotate
(L, (i), -1), lua_settop(L, -(1)-1)); return *p; } else return
((void*)0);} typedef int dummyTreeItem
;
56/* <<lua_class_TreeItem,`TreeItem`>>s represent information in the https://www.wireshark.org/docs/wsug_html_chunked/ChUsePacketDetailsPaneSection.html[packet details] pane of Wireshark, and the packet details view of TShark.
57 A <<lua_class_TreeItem,`TreeItem`>> represents a node in the tree, which might also be a subtree and have a list of children.
58 The children of a subtree have zero or more siblings which are other children of the same <<lua_class_TreeItem,`TreeItem`>> subtree.
59
60 During dissection, heuristic-dissection, and post-dissection, a root <<lua_class_TreeItem,`TreeItem`>> is passed to dissectors as the third argument of the function
61 callback (e.g., `myproto.dissector(tvbuf,pktinfo,root)`).
62
63 In some cases the tree is not truly added to, in order to improve performance.
64 For example for packets not currently displayed/selected in Wireshark's visible
65 window pane, or if TShark isn't invoked with the `-V` switch. However the
66 "add" type <<lua_class_TreeItem,`TreeItem`>> functions can still be called, and still return <<lua_class_TreeItem,`TreeItem`>>
67 objects - but the info isn't really added to the tree. Therefore you do not
68 typically need to worry about whether there's a real tree or not. If, for some
69 reason, you need to know it, you can use the <<lua_class_attrib_treeitem_visible,`TreeItem.visible`>> attribute getter
70 to retrieve the state.
71 */
72
73/* the following is used by TreeItem_add_packet_field() - this can THROW errors */
74static proto_item *
75try_add_packet_field(lua_State *L, TreeItem tree_item, TvbRange tvbr, const int hfid,
76 const ftenum_t type, const unsigned encoding, int *ret_err)
77{
78 int err = 0;
79 proto_item *volatile item = NULL((void*)0);
80 unsigned endoff = 0;
81
82 switch(type) {
83 /* these all generate ByteArrays */
84 case FT_BYTES:
85 case FT_UINT_BYTES:
86 case FT_OID:
87 case FT_REL_OID:
88 case FT_SYSTEM_ID:
89 {
90 /* GByteArray and its data will be g_free'd by Lua */
91 GByteArray *gba = g_byte_array_new();
92 item = proto_tree_add_bytes_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
93 tvbr->offset, tvbr->len, encoding,
94 gba, &endoff, &err);
95 if (err == 0) {
96 pushByteArray(L, gba);
97 lua_pushinteger(L, endoff);
98 }
99 }
100 break;
101
102 case FT_ABSOLUTE_TIME:
103 case FT_RELATIVE_TIME:
104 {
105 /* nstime_t will be g_free'd by Lua */
106 nstime_t *nstime = g_new0(nstime_t, 1)((nstime_t *) g_malloc0_n ((1), sizeof (nstime_t)));
107 item = proto_tree_add_time_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
108 tvbr->offset, tvbr->len, encoding,
109 nstime, &endoff, &err);
110 if (err == 0) {
111 pushNSTime(L,nstime);
112 lua_pushinteger(L, endoff);
113 }
114 }
115 break;
116
117 case FT_INT8:
118 case FT_INT16:
119 case FT_INT24:
120 case FT_INT32:
121 {
122 int32_t ret;
123 item = proto_tree_add_item_ret_int(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
124 tvbr->offset, tvbr->len, encoding,
125 &ret);
126 lua_pushinteger(L, (lua_Integer)ret);
127 lua_pushinteger(L, tvbr->offset + tvbr->len);
128 }
129 break;
130
131 case FT_INT40:
132 case FT_INT48:
133 case FT_INT56:
134 case FT_INT64:
135 {
136 int64_t ret;
137 item = proto_tree_add_item_ret_int64(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
138 tvbr->offset, tvbr->len, encoding,
139 &ret);
140 pushInt64(L, ret);
141 lua_pushinteger(L, tvbr->offset + tvbr->len);
142 }
143 break;
144
145 case FT_CHAR:
146 case FT_UINT8:
147 case FT_UINT16:
148 case FT_UINT24:
149 case FT_UINT32:
150 {
151 uint32_t ret;
152 item = proto_tree_add_item_ret_uint(tree_item-> tree, hfid, tvbr->tvb->ws_tvb,
153 tvbr->offset, tvbr->len, encoding,
154 &ret);
155 lua_pushinteger(L, (lua_Integer)ret);
156 lua_pushinteger(L, tvbr->offset + tvbr->len);
157 }
158 break;
159
160 case FT_UINT40:
161 case FT_UINT48:
162 case FT_UINT56:
163 case FT_UINT64:
164 {
165 uint64_t ret;
166 item = proto_tree_add_item_ret_uint64(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
167 tvbr->offset, tvbr->len, encoding,
168 &ret);
169 pushUInt64(L, ret);
170 lua_pushinteger(L, tvbr->offset + tvbr->len);
171 }
172 break;
173
174 case FT_BOOLEAN:
175 {
176 bool_Bool ret;
177 item = proto_tree_add_item_ret_boolean(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
178 tvbr->offset, tvbr->len, encoding,
179 &ret);
180 lua_pushboolean(L, ret);
181 lua_pushinteger(L, tvbr->offset + tvbr->len);
182 }
183 break;
184
185 case FT_STRING:
186 case FT_STRINGZ:
187 case FT_STRINGZPAD:
188 case FT_STRINGZTRUNC:
189 case FT_UINT_STRING:
190 {
191 const uint8_t *ret;
192 int len;
193 item = proto_tree_add_item_ret_string_and_length(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
194 tvbr->offset, tvbr->len, encoding,
195 NULL((void*)0), &ret, &len);
196 lua_pushstring(L, (const char*)ret);
197 lua_pushinteger(L, tvbr->offset + len);
198 wmem_free(NULL((void*)0), (void*)ret);
199 }
200 break;
201
202 case FT_FLOAT:
203 {
204 float ret;
205 item = proto_tree_add_item_ret_float(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
206 tvbr->offset, tvbr->len, encoding,
207 &ret);
208 lua_pushnumber(L, (lua_Number)ret);
209 lua_pushinteger(L, tvbr->offset + tvbr->len);
210 }
211 break;
212
213 case FT_DOUBLE:
214 {
215 double ret;
216 item = proto_tree_add_item_ret_double(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
217 tvbr->offset, tvbr->len, encoding,
218 &ret);
219 lua_pushnumber(L, (lua_Number)ret);
220 lua_pushinteger(L, tvbr->offset + tvbr->len);
221 }
222 break;
223
224 case FT_IPv4:
225 {
226 Address addr = g_new(address,1)((address *) g_malloc_n ((1), sizeof (address)));
227 ws_in4_addr ret;
228 item = proto_tree_add_item_ret_ipv4(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
229 tvbr->offset, tvbr->len, encoding,
230 &ret);
231 alloc_address_wmem(NULL((void*)0), addr, AT_IPv4, sizeof(ret), &ret);
232 pushAddress(L, addr);
233 lua_pushinteger(L, tvbr->offset + tvbr->len);
234 }
235 break;
236
237 case FT_IPv6:
238 {
239 Address addr = g_new(address, 1)((address *) g_malloc_n ((1), sizeof (address)));
240 ws_in6_addr ret;
241 item = proto_tree_add_item_ret_ipv6(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
242 tvbr->offset, tvbr->len, encoding,
243 &ret);
244 alloc_address_wmem(NULL((void*)0), addr, AT_IPv6, sizeof(ret), &ret);
245 pushAddress(L, addr);
246 lua_pushinteger(L, tvbr->offset + tvbr->len);
247 }
248 break;
249
250 case FT_ETHER:
251 {
252 Address addr = g_new(address, 1)((address *) g_malloc_n ((1), sizeof (address)));
253 uint8_t bytes[FT_ETHER_LEN6];
254
255 item = proto_tree_add_item_ret_ether(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
256 tvbr->offset, tvbr->len, encoding,
257 bytes);
258 alloc_address_wmem(NULL((void*)0), addr, AT_ETHER, sizeof(bytes), bytes);
259 pushAddress(L, addr);
260 lua_pushinteger(L, tvbr->offset + tvbr->len);
261 }
262 break;
263
264 default:
265 item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, encoding);
266 lua_pushnil(L);
267 lua_pushnil(L);
268 break;
269 }
270
271 if (ret_err) *ret_err = err;
272
273 return item;
274}
275
276WSLUA_METHODstatic int TreeItem_add_packet_field(lua_State *L) {
277 /*
278 Adds a new child tree for the given <<lua_class_ProtoField,`ProtoField`>> object to this tree item,
279 returning the new child <<lua_class_TreeItem,`TreeItem`>>.
280
281 Unlike `TreeItem:add()` and `TreeItem:add_le()`, the <<lua_class_ProtoField,`ProtoField`>> argument
282 is not optional, and cannot be a `Proto` object. Instead, this function always
283 uses the <<lua_class_ProtoField,`ProtoField`>> to determine the type of field to extract from the
284 passed-in `TvbRange`, highlighting the relevant bytes in the Packet Bytes pane
285 of the GUI (if there is a GUI), etc. If no <<lua_class_TvbRange,`TvbRange`>>is given, no bytes are
286 highlighted and the field's value cannot be determined; the <<lua_class_ProtoField,`ProtoField`>> must
287 have been defined/created not to have a length in such a case, or an error will
288 occur. For backwards-compatibility reasons the `encoding` argument, however,
289 must still be given.
290
291 Unlike `TreeItem:add()` and `TreeItem:add_le()`, this function performs both
292 big-endian and little-endian decoding, by setting the `encoding` argument to
293 be `ENC_BIG_ENDIAN` or `ENC_LITTLE_ENDIAN`.
294
295 The signature of this function:
296
297 [source,lua]
298 ----
299 tree_item:add_packet_field(proto_field [,tvbrange], encoding, ...)
300 ----
301
302 This function returns more than just the new child <<lua_class_TreeItem,`TreeItem`>>.
303 The child is the first return value, so that function chaining will still work; but it
304 also returns more information. The second return is the value of the extracted field
305 (i.e., a number, `UInt64`, `Address`, etc.). The third return is is the offset where
306 data should be read next. This is useful when the length of the field is not known in
307 advance. The additional return values may be null if the field type is not well supported
308 in the Lua API.
309
310 This function can extract a <<lua_class_ProtoField,`ProtoField`>> of type `ftypes.BYTES`
311 or `ftypes.ABSOLUTE_TIME` from a string in the `TvbRange` in ASCII-based and similar
312 encodings. For example, a `ProtoField` of `ftypes.BYTES` can be extracted from a `TvbRange`
313 containing the ASCII string "a1b2c3d4e5f6", and it will correctly decode the ASCII both in the
314 tree as well as for the second return value, which will be a <<lua_class_ByteArray,`ByteArray`>>.
315 To do so, you must set the `encoding` argument of this function to the appropriate string `ENC_*`
316 value, bitwise-or'd (or added) with the `ENC_STR_HEX` value and one or more `ENC_SEP_XXX` values
317 indicating which encodings are allowed. For `ftypes.ABSOLUTE_TIME`, one of the `ENC_ISO_8601_*`
318 encodings or `ENC_IMF_DATE_TIME` must be used, and the second return value is a <<lua_class_NSTime,`NSTime`>>.
319 Only single-byte ASCII digit string encodings such as `ENC_ASCII` and `ENC_UTF_8` can be used for this.
320
321 For example, assuming the <<lua_class_Tvb,`Tvb`>> named "`tvb`" contains the string "abcdef"
322 (61 62 63 64 65 66 in hex):
323
324 [source,lua]
325 ----
326 -- this is done earlier in the script
327 local myfield = ProtoField.new("Transaction ID", "myproto.trans_id", ftypes.BYTES)
328 myproto.fields = { myfield }
329
330 -- this is done inside a dissector, post-dissector, or heuristic function
331 -- child will be the created child tree, and value will be the ByteArray "abcdef" or nil on failure
332 local child, value = tree:add_packet_field(myfield, tvb:range(0,6), ENC_UTF_8 + ENC_STR_HEX + ENC_SEP_NONE)
333 ----
334
335 */
336#define WSLUA_ARG_TreeItem_add_packet_field_PROTOFIELD2 2 /* The ProtoField field object to add to the tree. */
337#define WSLUA_OPTARG_TreeItem_add_packet_field_TVBRANGE3 3 /* The <<lua_class_TvbRange,`TvbRange`>> of bytes in the packet this tree item covers/represents. */
338#define WSLUA_ARG_TreeItem_add_packet_field_ENCODING4 4 /* The field's encoding in the `TvbRange`. */
339#define WSLUA_OPTARG_TreeItem_add_packet_field_LABEL5 5 /* One or more strings to append to the created <<lua_class_TreeItem,`TreeItem`>>. */
340 volatile TvbRange tvbr;
341 ProtoField field;
342 int hfid;
343 volatile int ett;
344 ftenum_t type;
345 TreeItem tree_item = shiftTreeItem(L,1);
346 unsigned encoding;
347 proto_item* item = NULL((void*)0);
348 volatile int nargs;
349 volatile int err = 0;
350 const char *volatile error = NULL((void*)0);
351
352 if (!tree_item) {
353 return luaL_error(L,"not a TreeItem!");
354 }
355 if (tree_item->expired) {
356 luaL_error(L,"expired TreeItem");
357 return 0;
358 }
359
360 if (! ( field = shiftProtoField(L,1) ) ) {
361 luaL_error(L,"TreeField:add_packet_field not passed a ProtoField");
362 return 0;
363 }
364 if (field->hfid == -2) {
365 luaL_error(L, "ProtoField %s unregistered (not added to a Proto.fields attribute)", field->abbrev);
366 }
367 hfid = field->hfid;
368 type = field->type;
369 ett = field->ett;
370
371 tvbr = shiftTvbRange(L,1);
372 if (!tvbr) {
373 /* No TvbRange specified */
374 tvbr = wmem_new(lua_pinfo->pool, struct _wslua_tvbrange)((struct _wslua_tvbrange*)wmem_alloc((lua_pinfo->pool), sizeof
(struct _wslua_tvbrange)))
;
375 tvbr->tvb = wmem_new(lua_pinfo->pool, struct _wslua_tvb)((struct _wslua_tvb*)wmem_alloc((lua_pinfo->pool), sizeof(
struct _wslua_tvb)))
;
376 tvbr->tvb->ws_tvb = lua_tvb;
377 tvbr->offset = 0;
378 tvbr->len = 0;
379 }
380
381 encoding = wslua_checkuint(L,1)(unsigned) ( luaL_checkinteger(L,1) );
382 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
383
384 /* get the number of additional args before we add more to the stack */
385 nargs = lua_gettop(L);
386
387 /* XXX: why is this being done? If the length was -1, FT_STRINGZ figures out
388 * the right length in tvb_get_stringz_enc(); if it was 0, it should remain zero;
389 * if it was greater than zero, then it's the length the caller wanted.
390 */
391 if (type == FT_STRINGZ) {
392 switch (encoding & ENC_CHARENCODING_MASK0x0000FFFE) {
393
394 case ENC_UTF_160x00000004:
395 case ENC_UCS_20x00000006:
396 tvbr->len = tvb_unicode_strsize (tvbr->tvb->ws_tvb, tvbr->offset);
397 break;
398
399 default:
400 if (!tvb_find_uint8_remaining(tvbr->tvb->ws_tvb, tvbr->offset, 0, NULL((void*)0))) {
401 luaL_error(L,"out of bounds");
402 return 0;
403 }
404 tvbr->len = tvb_strsize (tvbr->tvb->ws_tvb, tvbr->offset);
405 break;
406 }
407 }
408
409 TRY{ except_t *volatile exc; volatile int except_state = 0; static
const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode
except_sn; struct except_catch except_ch; except_setup_try(&
except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch
.except_jmp)) *(&exc) = &except_ch.except_obj; else *
(&exc) = 0; if(except_state & 1) except_state |= 2; except_state
&= ~1; if (except_state == 0 && exc == 0)
{
410 int errx = 0;
411 item = try_add_packet_field(L, tree_item, tvbr, hfid, type, encoding, &errx);
412 err = errx;
413 } CATCH_ALLif (except_state == 0 && exc != 0 && (except_state
|=1))
{
414 show_exception(tvbr->tvb->ws_tvb, lua_pinfo, tree_item->tree, EXCEPT_CODE((exc)->except_id.except_code), GET_MESSAGE((exc)->except_message));
415 error = "Lua programming error";
416 } ENDTRYif(!(except_state&1) && exc != 0) except_rethrow(
exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}
;
417
418 if (error) { WSLUA_ERROR(TreeItem_add_packet_field,error){ luaL_error(L, "%s%s", "TreeItem_add_packet_field" ": ", error
); }
; }
419
420 if (err != 0) {
421 lua_pushnil(L);
422 lua_pushnil(L);
423 }
424
425 while(nargs) {
426 const char* s;
427 s = lua_tostring(L,1)lua_tolstring(L, (1), ((void*)0));
428 if (s) proto_item_append_text(item, " %s", s);
429 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
430 nargs--;
431 }
432
433 push_TreeItem(L, proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett), item);
434
435 /* move the tree object before the field value */
436 lua_insert(L, 1)lua_rotate(L, (1), 1);
437
438 WSLUA_RETURN(3)return (3); /* The new child <<lua_class_TreeItem,`TreeItem`>>, the field's extracted value or nil, and offset or nil. */
439}
440
441/* The following is used by TreeItem_add() and TreeItem_le() and can THROW.
442 * It should be called inside a TRY (e.g. WRAP_NON_LUA_EXCEPTIONS) block and
443 * THROW_LUA_ERROR should be used insteadof lua[L]_error.
444 */
445static int TreeItem_add_item_any(lua_State *L, bool_Bool little_endian) {
446 TvbRange tvbr;
447 Proto proto;
448 ProtoField field;
449 int hfid = -1;
450 int ett = -1;
451 ftenum_t type = FT_NONE;
452 TreeItem tree_item = shiftTreeItem(L,1);
453 proto_item* item = NULL((void*)0);
454
455 if (!tree_item) {
456 THROW_LUA_ERROR("not a TreeItem!")except_throwf(1, (6), "not a TreeItem!");
457 }
458 if (tree_item->expired) {
459 THROW_LUA_ERROR("expired TreeItem")except_throwf(1, (6), "expired TreeItem");
460 return 0;
461 }
462
463 if (! ( field = shiftProtoField(L,1) ) ) {
464 if (( proto = shiftProto(L,1) )) {
465 hfid = proto->hfid;
466 type = FT_PROTOCOL;
467 ett = proto->ett;
468 } else if (lua_isnil(L, 1)(lua_type(L, (1)) == 0)) {
469 THROW_LUA_ERROR("first argument to TreeItem:add is nil!")except_throwf(1, (6), "first argument to TreeItem:add is nil!"
)
;
470 }
471 } else {
472 hfid = field->hfid;
473 type = field->type;
474 ett = field->ett;
475 }
476
477 tvbr = shiftTvbRange(L,1);
478
479 if (!tvbr) {
480 tvbr = wmem_new(lua_pinfo->pool, struct _wslua_tvbrange)((struct _wslua_tvbrange*)wmem_alloc((lua_pinfo->pool), sizeof
(struct _wslua_tvbrange)))
;
481 tvbr->tvb = wmem_new(lua_pinfo->pool, struct _wslua_tvb)((struct _wslua_tvb*)wmem_alloc((lua_pinfo->pool), sizeof(
struct _wslua_tvb)))
;
482 tvbr->tvb->ws_tvb = lua_tvb;
483 tvbr->offset = 0;
484 tvbr->len = 0;
485 }
486
487 if (hfid > 0 ) {
488 /* hfid is > 0 when the first arg was a ProtoField or Proto */
489
490 if (type == FT_STRINGZ) {
491 if (!tvb_find_uint8_remaining(tvbr->tvb->ws_tvb, tvbr->offset, 0, NULL((void*)0))) {
492 THROW_LUA_ERROR("out of bounds")except_throwf(1, (6), "out of bounds");
493 return 0;
494 }
495 tvbr->len = tvb_strsize (tvbr->tvb->ws_tvb, tvbr->offset);
496 }
497
498 if (lua_gettop(L)) {
499 /* if we got here, the (L,1) index is the value to add, instead of decoding from the Tvb */
500
501 /* It's invalid for it to be nil (which has been documented for
502 * a long time). Make sure we throw our error instead of an
503 * internal Lua error (due to nested setjmp/longjmp).
504 */
505 if (lua_isnil(L, 1)(lua_type(L, (1)) == 0)) {
506 THROW_LUA_ERROR("TreeItem:add value argument is nil!")except_throwf(1, (6), "TreeItem:add value argument is nil!");
507 }
508
509 switch(type) {
510 case FT_PROTOCOL:
511 item = proto_tree_add_item(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,ENC_NA0x00000000);
512 lua_pushinteger(L,0);
513 lua_insert(L,1)lua_rotate(L, (1), 1);
514 break;
515 case FT_BOOLEAN:
516 {
517 uint64_t val;
518 switch(lua_type(L, 1)) {
519
520 case LUA_TUSERDATA7:
521 val = checkUInt64(L, 1);
522 break;
523
524 default:
525 /* this needs to use checkinteger so that it can accept a Lua boolean and coerce it to an int */
526 val = (uint64_t) (wslua_tointeger(L,1));
527 }
528 item = proto_tree_add_boolean(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,val);
529 }
530 break;
531 case FT_CHAR:
532 case FT_UINT8:
533 case FT_UINT16:
534 case FT_UINT24:
535 case FT_UINT32:
536 case FT_FRAMENUM:
537 item = proto_tree_add_uint(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,wslua_checkuint32(L,1)(uint32_t) ( luaL_checkinteger(L,1) ));
538 break;
539 case FT_INT8:
540 case FT_INT16:
541 case FT_INT24:
542 case FT_INT32:
543 item = proto_tree_add_int(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,wslua_checkint32(L,1)(int32_t) ( luaL_checkinteger(L,1) ));
544 break;
545 case FT_FLOAT:
546 item = proto_tree_add_float(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,(float)luaL_checknumber(L,1));
547 break;
548 case FT_DOUBLE:
549 item = proto_tree_add_double(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,(double)luaL_checknumber(L,1));
550 break;
551 case FT_ABSOLUTE_TIME:
552 case FT_RELATIVE_TIME:
553 item = proto_tree_add_time(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,checkNSTime(L,1));
554 break;
555 case FT_STRING:
556 case FT_STRINGZ:
557 item = proto_tree_add_string(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,luaL_checkstring(L,1)(luaL_checklstring(L, (1), ((void*)0))));
558 break;
559 case FT_BYTES:
560 item = proto_tree_add_bytes(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len, (const uint8_t*) luaL_checkstring(L,1)(luaL_checklstring(L, (1), ((void*)0))));
561 break;
562 case FT_UINT64:
563 item = proto_tree_add_uint64(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,checkUInt64(L,1));
564 break;
565 case FT_INT64:
566 item = proto_tree_add_int64(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,checkInt64(L,1));
567 break;
568 case FT_IPv4:
569 {
570 Address addr = checkAddress(L,1);
571 uint32_t addr_value;
572
573 if (addr->type != AT_IPv4) {
574 THROW_LUA_ERROR("Expected IPv4 address for FT_IPv4 field")except_throwf(1, (6), "Expected IPv4 address for FT_IPv4 field"
)
;
575 return 0;
576 }
577
578 /*
579 * The address is not guaranteed to be aligned on a
580 * 32-bit boundary, so we can't safely dereference
581 * the pointer as if it were so aligned.
582 */
583 memcpy(&addr_value, addr->data, sizeof addr_value);
584 item = proto_tree_add_ipv4(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,addr_value);
585 }
586 break;
587 case FT_IPv6:
588 {
589 Address addr = checkAddress(L,1);
590 if (addr->type != AT_IPv6) {
591 THROW_LUA_ERROR("Expected IPv6 address for FT_IPv6 field")except_throwf(1, (6), "Expected IPv6 address for FT_IPv6 field"
)
;
592 return 0;
593 }
594
595 item = proto_tree_add_ipv6(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, (const ws_in6_addr *)addr->data);
596 }
597 break;
598 case FT_ETHER:
599 {
600 Address addr = checkAddress(L,1);
601 if (addr->type != AT_ETHER) {
602 THROW_LUA_ERROR("Expected MAC address for FT_ETHER field")except_throwf(1, (6), "Expected MAC address for FT_ETHER field"
)
;
603 return 0;
604 }
605
606 item = proto_tree_add_ether(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, (const uint8_t *)addr->data);
607 }
608 break;
609 case FT_UINT_BYTES:
610 case FT_IPXNET:
611 case FT_GUID:
612 case FT_OID:
613 case FT_REL_OID:
614 case FT_SYSTEM_ID:
615 case FT_VINES:
616 case FT_FCWWN:
617 default:
618 THROW_LUA_ERROR("%s not yet supported", ftype_name(type))except_throwf(1, (6), "%s not yet supported", ftype_name(type
))
;
619 return 0;
620 }
621
622 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
623
624 } else {
625 if (type == FT_FRAMENUM) {
626 THROW_LUA_ERROR("ProtoField FRAMENUM cannot fetch value from Tvb")except_throwf(1, (6), "ProtoField FRAMENUM cannot fetch value from Tvb"
)
;
627 return 0;
628 }
629 /* the Lua stack is empty - no value was given - so decode the value from the tvb */
630 item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, little_endian ? ENC_LITTLE_ENDIAN0x80000000 : ENC_BIG_ENDIAN0x00000000);
631 }
632
633 if ( lua_gettop(L) ) {
634 /* if there was a value, it was removed earlier, so what's left is the display string to set */
635 const char* s = lua_tostring(L,1)lua_tolstring(L, (1), ((void*)0));
636 if (s) proto_item_set_text(item,"%s",s);
637 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
638 }
639
640 } else {
641 /* no ProtoField or Proto was given - we're adding a text-only field,
642 * any remaining parameters are parts of the text label. */
643 if (lua_gettop(L)) {
644 const char* s = lua_tostring(L,1)lua_tolstring(L, (1), ((void*)0));
645 const int hf = get_hf_wslua_text();
646 if (hf > -1) {
647 /* use proto_tree_add_none_format() instead? */
648 item = proto_tree_add_item(tree_item->tree, hf, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, ENC_NA0x00000000);
649 proto_item_set_text(item, "%s", s);
650 } else {
651 THROW_LUA_ERROR("Internal error: hf_wslua_text not registered")except_throwf(1, (6), "Internal error: hf_wslua_text not registered"
)
;
652 }
653 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
654 } else {
655 THROW_LUA_ERROR("Tree item ProtoField/Protocol handle is invalid (ProtoField/Proto not registered?)")except_throwf(1, (6), "Tree item ProtoField/Protocol handle is invalid (ProtoField/Proto not registered?)"
)
;
656 }
657 }
658
659 while(lua_gettop(L)) {
660 /* keep appending more text */
661 const char* s = lua_tostring(L,1)lua_tolstring(L, (1), ((void*)0));
662 if (s) proto_item_append_text(item, " %s", s);
663 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
664 }
665
666 push_TreeItem(L, proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett), item);
667
668 return 1;
669}
670
671
672WSLUA_METHODstatic int TreeItem_add(lua_State *L) {
673 /*
674 Adds a child item to this tree item, returning the new child <<lua_class_TreeItem,`TreeItem`>>.
675
676 If the <<lua_class_ProtoField,`ProtoField`>> represents a numeric value (int, uint or float), then it's treated as a Big Endian (network order) value.
677
678 This function has a complicated form: 'treeitem:add([protofield,] [tvbrange,] [[value], label]])', such that if the first
679 argument is a <<lua_class_ProtoField,`ProtoField`>> or a <<lua_class_Proto,`Proto`>>, the second argument is a <<lua_class_TvbRange,`TvbRange`>>, and a third argument is given, it's a value;
680 but if the second argument is a non-<<lua_class_TvbRange,`TvbRange`>>, then it's the value (as opposed to filling that argument with 'nil',
681 which is invalid for this function). If the first argument is a non-<<lua_class_ProtoField,`ProtoField`>> and a non-<<lua_class_Proto,`Proto`>> then this argument can
682 be either a <<lua_class_TvbRange,`TvbRange`>> or a label, and the value is not in use.
683
684 [discrete]
685 ====== Example
686
687 [source,lua]
688 ----
689 local proto_foo = Proto("foo", "Foo Protocol")
690 proto_foo.fields.bytes = ProtoField.bytes("foo.bytes", "Byte array")
691 proto_foo.fields.u16 = ProtoField.uint16("foo.u16", "Unsigned short", base.HEX)
692
693 function proto_foo.dissector(buf, pinfo, tree)
694 -- ignore packets less than 4 bytes long
695 if buf:len() < 4 then return end
696
697 -- ##############################################
698 -- # Assume buf(0,4) == {0x00, 0x01, 0x00, 0x02}
699 -- ##############################################
700
701 local t = tree:add( proto_foo, buf() )
702
703 -- Adds a byte array that shows as: "Byte array: 00010002"
704 t:add( proto_foo.fields.bytes, buf(0,4) )
705
706 -- Adds a byte array that shows as "Byte array: 313233"
707 -- (the ASCII char code of each character in "123")
708 t:add( proto_foo.fields.bytes, buf(0,4), "123" )
709
710 -- Adds a tree item that shows as: "Unsigned short: 0x0001"
711 t:add( proto_foo.fields.u16, buf(0,2) )
712
713 -- Adds a tree item that shows as: "Unsigned short: 0x0064"
714 t:add( proto_foo.fields.u16, buf(0,2), 100 )
715
716 -- Adds a tree item that shows as: "Unsigned short: 0x0064 ( big endian )"
717 t:add( proto_foo.fields.u16, buf(1,2), 100, nil, "(", nil, "big", 999, nil, "endian", nil, ")" )
718
719 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x0100"
720 t:add_le( proto_foo.fields.u16, buf(0,2) )
721
722 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x6400"
723 t:add_le( proto_foo.fields.u16, buf(0,2), 100 )
724
725 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x6400 ( little endian )"
726 t:add_le( proto_foo.fields.u16, buf(1,2), 100, nil, "(", nil, "little", 999, nil, "endian", nil, ")" )
727 end
728
729 udp_table = DissectorTable.get("udp.port")
730 udp_table:add(7777, proto_foo)
731 ----
732 */
733#define WSLUA_OPTARG_TreeItem_add_PROTOFIELD2 2 /* The <<lua_class_ProtoField,`ProtoField`>> field or <<lua_class_Proto,`Proto`>> protocol object to add to the tree. */
734#define WSLUA_OPTARG_TreeItem_add_TVBRANGE3 3 /* The <<lua_class_TvbRange,`TvbRange`>> of bytes in the packet this tree item covers/represents. */
735#define WSLUA_OPTARG_TreeItem_add_VALUE4 4 /* The field's value, instead of the ProtoField/Proto one. */
736#define WSLUA_OPTARG_TreeItem_add_LABEL5 5 /* One or more strings to use for the tree item label, instead of the ProtoField/Proto one. */
737
738 volatile int ret;
1
'ret' declared without an initial value
739 WRAP_NON_LUA_EXCEPTIONS({ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,0)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
2
Assuming the condition is true
3
Taking true branch
4
Taking false branch
5
Taking false branch
6
Assuming field 'except_code' is equal to 1
7
Taking true branch
8
Taking false branch
740 ret = TreeItem_add_item_any(L,false);{ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,0)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
741 ){ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,0)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
742 WSLUA_RETURN(ret)return (ret); /* The new child TreeItem. */
9
Undefined or garbage value returned to caller
743}
744
745WSLUA_METHODstatic int TreeItem_add_le(lua_State *L) {
746 /*
747 Adds a child item to this tree item, returning the new child <<lua_class_TreeItem,`TreeItem`>>.
748
749 If the <<lua_class_ProtoField,`ProtoField`>> represents a numeric value (int, uint or float), then it's treated as a Little Endian value.
750
751 This function has a complicated form: 'treeitem:add_le([protofield,] [tvbrange,] [[value], label]])', such that if the first
752 argument is a <<lua_class_ProtoField,`ProtoField`>> or a <<lua_class_Proto,`Proto`>>, the second argument is a <<lua_class_TvbRange,`TvbRange`>>, and a third argument is given, it's a value;
753 but if the second argument is a non-<<lua_class_TvbRange,`TvbRange`>>, then it's the value (as opposed to filling that argument with 'nil',
754 which is invalid for this function). If the first argument is a non-<<lua_class_ProtoField,`ProtoField`>> and a non-<<lua_class_Proto,`Proto`>> then this argument can
755 be either a <<lua_class_TvbRange,`TvbRange`>> or a label, and the value is not in use.
756 */
757#define WSLUA_OPTARG_TreeItem_add_le_PROTOFIELD2 2 /* The ProtoField field or Proto protocol object to add to the tree. */
758#define WSLUA_OPTARG_TreeItem_add_le_TVBRANGE3 3 /* The TvbRange of bytes in the packet this tree item covers/represents. */
759#define WSLUA_OPTARG_TreeItem_add_le_VALUE4 4 /* The field's value, instead of the ProtoField/Proto one. */
760#define WSLUA_OPTARG_TreeItem_add_le_LABEL5 5 /* One or more strings to use for the tree item label, instead of the ProtoField/Proto one. */
761 volatile int ret;
762 WRAP_NON_LUA_EXCEPTIONS({ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,1)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
763 ret = TreeItem_add_item_any(L,true);{ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,1)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
764 ){ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,1)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
765 WSLUA_RETURN(ret)return (ret); /* The new child TreeItem. */
766}
767
768/* WSLUA_ATTRIBUTE TreeItem_text RW Set/get the <<lua_class_TreeItem,`TreeItem`>>'s display string (string).
769
770 For the getter, if the TreeItem has no display string, then nil is returned.
771 */
772static int TreeItem_get_text(lua_State* L) {
773 TreeItem ti = checkTreeItem(L,1);
774 char label_str[ITEM_LABEL_LENGTH240+1];
775 char *label_ptr;
776
777 if (ti->item && PITEM_FINFO(ti->item)((ti->item)->finfo)) {
778 field_info *fi = PITEM_FINFO(ti->item)((ti->item)->finfo);
779
780 if (!fi->rep) {
781 label_ptr = label_str;
782 proto_item_fill_label(fi, label_str, NULL((void*)0));
783 } else
784 label_ptr = fi->rep->representation;
785
786 if (label_ptr) {
787 lua_pushstring(L, label_ptr);
788 } else {
789 lua_pushnil(L);
790 }
791 } else {
792 lua_pushnil(L);
793 }
794
795 return 1;
796}
797
798/* the following is used as both a method and attribute */
799WSLUA_METHODstatic int TreeItem_set_text(lua_State *L) {
800 /* Sets the text of the label.
801
802 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
803 */
804#define WSLUA_ARG_TreeItem_set_text_TEXT2 2 /* The text to be used. */
805 TreeItem ti = checkTreeItem(L,1);
806 const char* s = luaL_checkstring(L,WSLUA_ARG_TreeItem_set_text_TEXT)(luaL_checklstring(L, (2), ((void*)0)));
807
808 proto_item_set_text(ti->item,"%s",s);
809
810 /* copy the TreeItem userdata so we give it back */
811 lua_pushvalue(L, 1);
812
813 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
814}
815
816WSLUA_METHODstatic int TreeItem_append_text(lua_State *L) {
817 /* Appends text to the label.
818
819 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
820 */
821#define WSLUA_ARG_TreeItem_append_text_TEXT2 2 /* The text to be appended. */
822 TreeItem ti = checkTreeItem(L,1);
823 const char* s = luaL_checkstring(L,WSLUA_ARG_TreeItem_append_text_TEXT)(luaL_checklstring(L, (2), ((void*)0)));
824
825 proto_item_append_text(ti->item,"%s",s);
826
827 /* copy the TreeItem userdata so we give it back */
828 lua_pushvalue(L, 1);
829
830 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
831}
832
833WSLUA_METHODstatic int TreeItem_prepend_text(lua_State *L) {
834 /* Prepends text to the label.
835
836 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
837 */
838#define WSLUA_ARG_TreeItem_prepend_text_TEXT2 2 /* The text to be prepended. */
839 TreeItem ti = checkTreeItem(L,1);
840 const char* s = luaL_checkstring(L,WSLUA_ARG_TreeItem_prepend_text_TEXT)(luaL_checklstring(L, (2), ((void*)0)));
841
842 proto_item_prepend_text(ti->item,"%s",s);
843
844 /* copy the TreeItem userdata so we give it back */
845 lua_pushvalue(L, 1);
846
847 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
848}
849
850WSLUA_METHODstatic int TreeItem_add_expert_info(lua_State *L) {
851 /* Sets the expert flags of the item and adds expert info to the packet.
852
853 This function does *not* create a truly filterable expert info for a protocol.
854 Instead you should use `TreeItem.add_proto_expert_info()`.
855
856 Note: This function is provided for backwards compatibility only, and should not
857 be used in new Lua code. It may be removed in the future. You should only
858 use `TreeItem.add_proto_expert_info()`.
859 */
860#define WSLUA_OPTARG_TreeItem_add_expert_info_GROUP2 2 /* One of:
861 `PI_CHECKSUM`,
862 `PI_SEQUENCE`,
863 `PI_RESPONSE_CODE`,
864 `PI_REQUEST_CODE`,
865 `PI_UNDECODED`,
866 `PI_REASSEMBLE`,
867 `PI_MALFORMED`,
868 `PI_DEBUG`,
869 `PI_PROTOCOL`,
870 `PI_SECURITY`,
871 `PI_COMMENTS_GROUP`,
872 `PI_DECRYPTION`,
873 `PI_ASSUMPTION`,
874 `PI_DEPRECATED`,
875 `PI_RECEIVE`,
876 `PI_INTERFACE`,
877 or `PI_DISSECTOR_BUG`. */
878#define WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY3 3 /* One of:
879 `PI_COMMENT`,
880 `PI_CHAT`,
881 `PI_NOTE`,
882 `PI_WARN`,
883 or `PI_ERROR`. */
884#define WSLUA_OPTARG_TreeItem_add_expert_info_TEXT4 4 /* The text for the expert info display. */
885 TreeItem ti = checkTreeItem(L,1);
886 int group = (int)luaL_optinteger(L,WSLUA_OPTARG_TreeItem_add_expert_info_GROUP2,PI_DEBUG0x08000000);
887 int severity = (int)luaL_optinteger(L,WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY3,PI_CHAT0x00200000);
888 expert_field* ei_info = wslua_get_expert_field(group, severity);
889 const char* str;
890
891 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_expert_info_TEXT4) {
892 str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_expert_info_TEXT4);
893 expert_add_info_format(lua_pinfo, ti->item, ei_info, "%s", str);
894 } else {
895 expert_add_info(lua_pinfo, ti->item, ei_info);
896 }
897
898 /* copy the TreeItem userdata so we give it back */
899 lua_pushvalue(L, 1);
900
901 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
902}
903
904WSLUA_METHODstatic int TreeItem_add_proto_expert_info(lua_State *L) {
905 /* Sets the expert flags of the tree item and adds expert info to the packet. */
906#define WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT2 2 /* The <<lua_class_ProtoExpert,`ProtoExpert`>> object to add to the tree. */
907#define WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3 3 /* Text for the expert info display
908 (default is to use the registered
909 text). */
910 TreeItem ti = checkTreeItem(L,1);
911 ProtoExpert expert = checkProtoExpert(L,WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT2);
912 const char* str;
913
914 if (expert->ids.ei == EI_INIT_EI0 || expert->ids.hf == EI_INIT_HF0) {
915 luaL_error(L, "ProtoExpert is not registered");
916 return 0;
917 }
918
919 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3) {
920 str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3);
921 expert_add_info_format(lua_pinfo, ti->item, &expert->ids, "%s", str);
922 } else {
923 expert_add_info(lua_pinfo, ti->item, &expert->ids);
924 }
925
926 /* copy the TreeItem userdata so we give it back */
927 lua_pushvalue(L, 1);
928
929 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
930}
931
932WSLUA_METHODstatic int TreeItem_add_tvb_expert_info(lua_State *L) {
933 /* Sets the expert flags of the tree item and adds expert info to the packet
934 associated with the <<lua_class_Tvb,`Tvb`>> or <<lua_class_TvbRange,`TvbRange`>> bytes in the packet. */
935#define WSLUA_ARG_TreeItem_add_tvb_expert_info_EXPERT2 2 /* The <<lua_class_ProtoExpert,`ProtoExpert`>> object to add to the tree. */
936#define WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB3 3 /* The <<lua_class_Tvb,`Tvb`>> or <<lua_class_TvbRange,`TvbRange`>> object bytes to associate
937 the expert info with. */
938#define WSLUA_OPTARG_TreeItem_add_tvb_expert_info_TEXT4 4 /* Text for the expert info display
939 (default is to use the registered
940 text). */
941 TreeItem ti = checkTreeItem(L,1);
942 ProtoExpert expert = checkProtoExpert(L,WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT2);
943 TvbRange tvbr;
944 const char* str;
945
946 if (expert->ids.ei == EI_INIT_EI0 || expert->ids.hf == EI_INIT_HF0) {
947 luaL_error(L, "ProtoExpert is not registered");
948 return 0;
949 }
950
951 tvbr = shiftTvbRange(L,WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB3);
952
953 if (!tvbr) {
954 tvbr = wmem_new(lua_pinfo->pool, struct _wslua_tvbrange)((struct _wslua_tvbrange*)wmem_alloc((lua_pinfo->pool), sizeof
(struct _wslua_tvbrange)))
;
955 tvbr->tvb = shiftTvb(L,WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB3);
956 if (!tvbr->tvb) {
957 tvbr->tvb = wmem_new(lua_pinfo->pool, struct _wslua_tvb)((struct _wslua_tvb*)wmem_alloc((lua_pinfo->pool), sizeof(
struct _wslua_tvb)))
;
958 }
959 tvbr->tvb->ws_tvb = lua_tvb;
960 tvbr->offset = 0;
961 tvbr->len = 0;
962 }
963
964 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3) {
965 str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3);
966 proto_tree_add_expert_format(ti->tree, lua_pinfo, &expert->ids,
967 tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len,
968 "%s", str);
969 } else {
970 proto_tree_add_expert(ti->tree, lua_pinfo, &expert->ids,
971 tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len);
972 }
973
974 /* copy the TreeItem userdata so we give it back */
975 lua_pushvalue(L, 1);
976
977 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
978}
979
980
981/* WSLUA_ATTRIBUTE TreeItem_visible RO Get the <<lua_class_TreeItem,`TreeItem`>>'s subtree visibility status (boolean). */
982static int TreeItem_get_visible(lua_State* L) {
983 TreeItem ti = checkTreeItem(L,1);
984
985 if (ti->tree) {
986 lua_pushboolean(L, PTREE_DATA(ti->tree)((ti->tree)->tree_data)->visible);
987 }
988 else {
989 lua_pushboolean(L, false0);
990 }
991
992 return 1;
993}
994
995
996/* WSLUA_ATTRIBUTE TreeItem_generated RW Set/get the <<lua_class_TreeItem,`TreeItem`>>'s generated state (boolean). */
997static int TreeItem_get_generated(lua_State* L) {
998 TreeItem ti = checkTreeItem(L,1);
999
1000 lua_pushboolean(L, proto_item_is_generated(ti->item));
1001
1002 return 1;
1003}
1004
1005/* the following is used as both a method and attribute. As a method it defaults
1006 to setting the value, because that's what it used to do before. */
1007WSLUA_METHODstatic int TreeItem_set_generated(lua_State *L) {
1008 /* Marks the <<lua_class_TreeItem,`TreeItem`>> as a generated field (with data inferred but not contained in the packet).
1009
1010 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1011 */
1012#define WSLUA_OPTARG_TreeItem_set_generated_BOOL2 2 /* A Lua boolean, which if `true` sets the <<lua_class_TreeItem,`TreeItem`>>
1013 generated flag, else clears it (default=true) */
1014 TreeItem ti = checkTreeItem(L,1);
1015 bool_Bool set = wslua_optbool(L, WSLUA_OPTARG_TreeItem_set_generated_BOOL2, true1);
1016
1017 if (set) {
1018 proto_item_set_generated(ti->item);
1019 } else {
1020 if (ti->item)
1021 FI_RESET_FLAG(PITEM_FINFO(ti->item), FI_GENERATED)do { if (((ti->item)->finfo)) (((ti->item)->finfo
))->flags = (((ti->item)->finfo))->flags & ~(
0x00000002); } while(0)
;
1022 }
1023
1024 /* copy the TreeItem userdata so we give it back */
1025 lua_pushvalue(L, 1);
1026
1027 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
1028}
1029
1030/* WSLUA_ATTRIBUTE TreeItem_hidden RW Set/get <<lua_class_TreeItem,`TreeItem`>>'s hidden state (boolean). */
1031static int TreeItem_get_hidden(lua_State* L) {
1032 TreeItem ti = checkTreeItem(L,1);
1033
1034 lua_pushboolean(L, proto_item_is_hidden(ti->item));
1035
1036 return 1;
1037}
1038
1039/* the following is used as both a method and attribute. As a method it defaults
1040 to setting the value, because that's what it used to do before. */
1041WSLUA_METHODstatic int TreeItem_set_hidden(lua_State *L) {
1042 /*
1043 Marks the <<lua_class_TreeItem,`TreeItem`>> as a hidden field (neither displayed nor used in filters).
1044 Deprecated
1045
1046 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1047 */
1048#define WSLUA_OPTARG_TreeItem_set_hidden_BOOL2 2 /* A Lua boolean, which if `true` sets the <<lua_class_TreeItem,`TreeItem`>>
1049 hidden flag, else clears it. Default is `true`. */
1050 TreeItem ti = checkTreeItem(L,1);
1051 bool_Bool set = wslua_optbool(L, WSLUA_OPTARG_TreeItem_set_hidden_BOOL2, true1);
1052
1053 if (set) {
1054 proto_item_set_hidden(ti->item);
1055 } else {
1056 proto_item_set_visible(ti->item);
1057 }
1058
1059 /* copy the TreeItem userdata so we give it back */
1060 lua_pushvalue(L, 1);
1061
1062 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
1063}
1064
1065/* WSLUA_ATTRIBUTE TreeItem_len RW Set/get <<lua_class_TreeItem,`TreeItem`>>'s length inside tvb, after it has already been created. */
1066static int TreeItem_get_len(lua_State* L) {
1067 TreeItem ti = checkTreeItem(L,1);
1068 int len = 0;
1069
1070 /* XXX - this is *NOT* guaranteed to return a correct value! */
1071 len = proto_item_get_len(ti->item);
1072
1073 lua_pushinteger(L, len > 0 ? len : 0);
1074
1075 return 1;
1076}
1077
1078WSLUA_METHODstatic int TreeItem_set_len(lua_State *L) {
1079 /* Set <<lua_class_TreeItem,`TreeItem`>>'s length inside tvb, after it has already been created.
1080
1081 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1082 */
1083#define WSLUA_ARG_TreeItem_set_len_LEN2 2 /* The length to be used. */
1084 TreeItem ti = checkTreeItem(L,1);
1085 int len = (int)luaL_checkinteger(L,WSLUA_ARG_TreeItem_set_len_LEN2);
1086
1087 if (len < 0) {
1088 luaL_argerror(L,WSLUA_ARG_TreeItem_set_len_LEN2,"must be a positive value");
1089 return 0;
1090 }
1091
1092 proto_item_set_len(ti->item, len);
1093
1094 /* copy the TreeItem userdata so we give it back */
1095 lua_pushvalue(L, 1);
1096
1097 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
1098}
1099
1100WSLUA_METHODstatic int TreeItem_referenced(lua_State *L) {
1101 /* Checks if a <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>> is referenced by a filter/tap/UI.
1102
1103 If this function returns `false`, it means that the field (or dissector) does not need to be dissected
1104 and can be safely skipped. By skipping a field rather than dissecting it, the dissector will
1105 usually run faster since Wireshark will not do extra dissection work when it doesn't need the field.
1106
1107 You can use this in conjunction with the TreeItem.visible attribute. This function will always return
1108 true when the TreeItem is visible. When it is not visible and the field is not referenced, you can
1109 speed up the dissection by not dissecting the field as it is not needed for display or filtering.
1110
1111 This function takes one parameter that can be a <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>>.
1112 The <<lua_class_Dissector,`Dissector`>> form is useful when you need to decide whether to call a sub-dissector.
1113 */
1114#define WSLUA_ARG_TreeItem_referenced_PROTOFIELD2 2 /* The <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>> to check if referenced. */
1115 TreeItem ti = checkTreeItem(L, 1);
1116 if (!ti) return 0;
1117 ProtoField f = shiftProtoField(L, WSLUA_ARG_TreeItem_referenced_PROTOFIELD2);
1118 if (f) {
1119 lua_pushboolean(L, proto_field_is_referenced(ti->tree, f->hfid));
1120 }
1121 else {
1122 Dissector d = checkDissector(L, WSLUA_ARG_TreeItem_referenced_PROTOFIELD2);
1123 if (!d) return 0;
1124 lua_pushboolean(L, proto_field_is_referenced(ti->tree, dissector_handle_get_protocol_index(d)));
1125 }
1126 WSLUA_RETURN(1)return (1); /* A boolean indicating if the ProtoField/Dissector is referenced */
1127}
1128
1129WSLUA_METHODstatic int TreeItem_get_child_count(lua_State *L) {
1130 /* Returns the number of direct child tree items.
1131
1132 This method counts and returns the number of direct children of this tree item.
1133 Only immediate children are counted; grandchildren and deeper descendants are not included.
1134
1135 [source,lua]
1136 ----
1137 local tree = root:add(myproto, tvbuf())
1138 tree:add("Child 1")
1139 tree:add("Child 2")
1140
1141 local count = tree:get_child_count()
1142 -- count is now 2
1143 ----
1144
1145 @since 4.7.0
1146 */
1147
1148 /* Retrieve and validate the TreeItem from Lua stack position 1 */
1149 TreeItem ti = checkTreeItem(L, 1);
1150 if (!ti) {
1151 return 0;
1152 }
1153
1154 int count = 0;
1155 proto_tree *tree = ti->tree;
1156
1157 if (tree) {
1158 /* Get the first child node from the proto_tree structure */
1159 proto_node *current = ((proto_node *)tree)->first_child;
1160
1161 /* Iterate through the linked list of children using the 'next' pointer */
1162 while (current) {
1163 count++;
1164 current = current->next; /* Move to next sibling */
1165 }
1166 }
1167
1168 /* Push the count as an integer onto the Lua stack */
1169 lua_pushinteger(L, count);
1170 WSLUA_RETURN(1)return (1); /* The number of child tree items. */
1171}
1172
1173WSLUA_METHODstatic int TreeItem_get_parent(lua_State *L) {
1174 /* Returns the parent tree item.
1175
1176 Returns the parent tree item of this item, or nil if this is a root item
1177 (i.e., a top-level tree item added directly to the protocol tree).
1178
1179 [source,lua]
1180 ----
1181 local parent_tree = root:add(myproto, tvbuf())
1182 local child_tree = parent_tree:add("Child")
1183
1184 local parent = child_tree:get_parent()
1185 -- parent is the same as parent_tree
1186
1187 local root_parent = parent_tree:get_parent()
1188 -- root_parent is nil (assuming parent_tree is a root item)
1189 ----
1190 @since 4.7.0
1191 */
1192
1193 /* Retrieve and validate the TreeItem from Lua stack */
1194 TreeItem ti = checkTreeItem(L, 1);
1195 if (!ti) {
1196 return 0;
1197 }
1198
1199 proto_item *parent = NULL((void*)0);
1200
1201 if (ti->item) {
1202 /* Use Wireshark's built-in function to get the parent proto_item */
1203 parent = proto_item_get_parent(ti->item);
1204 }
1205
1206 if (parent) {
1207 /* Parent exists - get its subtree (may be NULL if parent has no children) */
1208 proto_tree *parent_tree = proto_item_get_subtree(parent);
1209
1210 /* Create a new Lua TreeItem object wrapping the parent and push it to Lua */
1211 push_TreeItem(L, parent_tree, parent);
1212 } else {
1213 /* No parent exists - this is a root item, return nil */
1214 lua_pushnil(L);
1215 }
1216
1217 WSLUA_RETURN(1)return (1); /* The parent TreeItem, or nil if this is a root item. */
1218}
1219
1220WSLUA_METHODstatic int TreeItem_get_child(lua_State *L) {
1221 /* Returns the child tree item at the specified index.
1222
1223 Returns the direct child TreeItem at the given index using 0-based indexing.
1224 This provides random access to child items by their position.
1225
1226 [source,lua]
1227 ----
1228 local tree = root:add(myproto, tvbuf())
1229 tree:add("First child") -- index 0
1230 tree:add("Second child") -- index 1
1231 tree:add("Third child") -- index 2
1232
1233 local first = tree:get_child(0) -- Returns first child
1234 local second = tree:get_child(1) -- Returns second child
1235 local invalid = tree:get_child(5) -- Returns nil (out of range)
1236 ----
1237 @since 4.7.0
1238 */
1239
1240#define WSLUA_ARG_TreeItem_get_child_INDEX2 2 /* The index of the child (0-based). */
1241 /* Retrieve and validate the TreeItem */
1242 TreeItem ti = checkTreeItem(L, 1);
1243 if (!ti)
1244 return 0;
1245
1246 /* Get the index parameter from Lua (must be an integer) */
1247 lua_Integer index = luaL_checkinteger(L, WSLUA_ARG_TreeItem_get_child_INDEX2);
1248
1249 /* Validate index - must be non-negative for 0-based indexing */
1250 if (index < 0) {
1251 WSLUA_ARG_ERROR(TreeItem_get_child, INDEX, "index must be non-negative"){ luaL_argerror(L,2, "TreeItem_get_child" ": " "index must be non-negative"
); }
;
1252 }
1253
1254 proto_node *current = NULL((void*)0);
1255
1256 if (ti->tree) {
1257 /* Get the first child in the linked list */
1258 current = ((proto_node *)ti->tree)->first_child;
1259 }
1260
1261 /* Navigate to the index-th child by following the 'next' pointers */
1262 lua_Integer current_index = 0;
1263 while (current && current_index < index) {
1264 current = current->next; /* Move to next sibling */
1265 current_index++;
1266 }
1267
1268 if (current) {
1269 /* Child found at the specified index */
1270 /* Get the subtree (may be NULL if this node has no children) */
1271 proto_tree *child_tree = proto_item_get_subtree((proto_item *)current);
1272
1273 /* Create and push the TreeItem to Lua */
1274 push_TreeItem(L, child_tree, (proto_item *)current);
1275 } else {
1276 /* Index out of range - no child exists at this position */
1277 lua_pushnil(L);
1278 }
1279
1280 WSLUA_RETURN(1)return (1); /* The child TreeItem at the specified index, or nil if out of range. */
1281}
1282
1283/* Structure to hold iterator state with optional field name filters and recursion */
1284typedef struct
1285{
1286 proto_node *current_node; /* Current node being processed in iteration */
1287 char **field_filters; /* Array of field name strings to match (e.g., "tcp.port") */
1288 int num_filters; /* Number of filter strings in the array */
1289 bool_Bool recursive; /* If true, iterate through entire subtree depth-first */
1290 proto_node **stack; /* Stack for recursive depth-first traversal */
1291 int stack_size; /* Number of nodes currently on the stack */
1292 int stack_capacity; /* Maximum capacity of stack (grows dynamically) */
1293} TreeItem_iterator_state;
1294
1295/* Helper function to push a node onto the stack for recursive iteration */
1296static void push_node_to_stack(TreeItem_iterator_state *state, proto_node *node) {
1297 if (!node)
1298 return;
1299
1300 /* Dynamically expand stack capacity if needed */
1301 if (state->stack_size >= state->stack_capacity) {
1302 /* Double capacity plus initial buffer to reduce reallocation frequency */
1303 state->stack_capacity = state->stack_capacity * 2 + 10;
1304 state->stack = (proto_node **)g_realloc(state->stack,
1305 state->stack_capacity * sizeof(proto_node *));
1306 }
1307
1308 /* Add node to top of stack and increment size */
1309 state->stack[state->stack_size++] = node;
1310}
1311
1312/* Helper function to pop a node from the stack */
1313static proto_node *pop_node_from_stack(TreeItem_iterator_state *state) {
1314 /* Check if stack is empty */
1315 if (state->stack_size <= 0)
1316 return NULL((void*)0);
1317
1318 /* Return top element and decrement stack size */
1319 return state->stack[--state->stack_size];
1320}
1321
1322/* Helper function for the children iterator with optional filtering and recursion */
1323static int TreeItem_children_iterator(lua_State *L) {
1324 /* Retrieve the iterator state from the closure's upvalue */
1325 TreeItem_iterator_state *state = (TreeItem_iterator_state *)lua_touserdata(L, lua_upvalueindex(1)((-1000000 - 1000) - (1)));
1326
1327 /* Continue iterating while we have nodes to process */
1328 /* Either from current sibling chain OR from recursive stack */
1329 while (state->current_node || (state->recursive && state->stack_size > 0)) {
1330 proto_node *node = NULL((void*)0);
1331
1332 if (state->current_node) {
1333 /* Process next node in current sibling chain */
1334 node = state->current_node;
1335 state->current_node = node->next; /* Advance to next sibling for next iteration */
1336 } else if (state->recursive && state->stack_size > 0) {
1337 /* No more siblings - pop from stack for recursive traversal */
1338 node = pop_node_from_stack(state);
1339 if (!node)
1340 continue; /* Stack had invalid entry, skip */
1341
1342 /* Set current_node to first child of popped node */
1343 /* This allows iteration through all siblings before going deeper */
1344 proto_tree *subtree = proto_item_get_subtree((proto_item *)node);
1345 if (subtree) {
1346 state->current_node = ((proto_node *)subtree)->first_child;
1347 }
1348 }
1349
1350 if (!node)
1351 continue; /* Safety check - should not happen */
1352
1353 /* IMPORTANT: For recursive mode, always add children to stack regardless of filter match
1354 * This ensures that even if the current node doesn't match the filter,
1355 * its children are still searched recursively (depth-first traversal)
1356 *
1357 * Example: If we filter for "tcp.port" but current node is "tcp.flags",
1358 * we still need to check if "tcp.flags" has "tcp.port" children
1359 */
1360 if (state->recursive) {
1361 proto_tree *subtree = proto_item_get_subtree((proto_item *)node);
1362 if (subtree) {
1363 /* Collect all children first (needed for reverse-order pushing) */
1364 proto_node *child = ((proto_node *)subtree)->first_child;
1365 proto_node **children = NULL((void*)0);
1366 int child_count = 0;
1367
1368 /* Count and collect all children in forward order */
1369 while (child) {
1370 child_count++;
1371 children = (proto_node **)g_realloc(children, child_count * sizeof(proto_node *));
1372 children[child_count - 1] = child;
1373 child = child->next;
1374 }
1375
1376 /* Push children in REVERSE order to stack */
1377 /* This ensures depth-first left-to-right traversal */
1378 /* (first child is on top of stack, gets popped first) */
1379 for (int i = child_count - 1; i >= 0; i--) {
1380 push_node_to_stack(state, children[i]);
1381 }
1382
1383 /* Free temporary children array */
1384 if (children)
1385 g_free(children);
1386 }
1387 }
1388
1389 /* Check if this node matches the filter criteria */
1390 bool_Bool matches = false0;
1391 if (state->num_filters > 0) {
1392 /* Filters are specified - check if node's field name matches any filter */
1393 field_info *finfo = node->finfo;
1394
1395 /* Ensure node has valid field_info with abbreviated name */
1396 if (finfo && finfo->hfinfo && finfo->hfinfo->abbrev) {
1397 /* Check against all filter strings (OR logic) */
1398 for (int i = 0; i < state->num_filters; i++) {
1399 if (strcmp(finfo->hfinfo->abbrev, state->field_filters[i]) == 0) {
1400 matches = true1;
1401 break; /* Found match, no need to check remaining filters */
1402 }
1403 }
1404 }
1405 /* If finfo is NULL or has no abbrev, matches remains false */
1406 } else {
1407 /* No filters specified - return all children/descendants */
1408 matches = true1;
1409 }
1410
1411 /* Only return matching nodes to Lua, but continue processing regardless
1412 * (children were already added to stack above for recursive mode) */
1413 if (matches) {
1414 /* Get the subtree for this matching node (may be NULL) */
1415 proto_tree *child_tree = proto_item_get_subtree((proto_item *)node);
1416
1417 /* Push matching TreeItem to Lua stack */
1418 push_TreeItem(L, child_tree, (proto_item *)node);
1419 return 1; /* Return 1 value to Lua iterator */
1420 }
1421
1422 /* If no match, continue to next node
1423 * Children are already on stack for recursive mode,
1424 * ensuring we don't miss matching descendants */
1425 }
1426
1427 /* No more nodes to process - iteration complete */
1428 return 0; /* Return no values - signals end of iteration to Lua */
1429}
1430
1431/* Garbage collector for the iterator state */
1432static int TreeItem_iterator_state_gc(lua_State *L) {
1433 /* Retrieve the iterator state userdata */
1434 TreeItem_iterator_state *state = (TreeItem_iterator_state *)lua_touserdata(L, 1);
1435
1436 /* Free the filter strings array */
1437 if (state->field_filters) {
1438 /* Free each individual filter string */
1439 for (int i = 0; i < state->num_filters; i++) {
1440 g_free(state->field_filters[i]);
1441 }
1442 /* Free the array itself */
1443 g_free(state->field_filters);
1444 }
1445
1446 /* Free the recursion stack */
1447 if (state->stack) {
1448 g_free(state->stack);
1449 }
1450
1451 /* Note: The state struct itself is freed by Lua's GC */
1452 return 0;
1453}
1454
1455WSLUA_METHODstatic int TreeItem_children(lua_State *L) {
1456 /* Returns an iterator function to iterate over child tree items.
1457
1458 Returns an iterator function that can be used in a Lua for loop to iterate
1459 over children of this tree item. Supports optional filtering and recursive traversal.
1460
1461 The basic usage iterates over direct children only:
1462 [source,lua]
1463 ----
1464 for child in tree:children() do
1465 print("Child: " .. tostring(child))
1466 end
1467 ----
1468
1469 You can filter by field names to only get children with specific fields:
1470 [source,lua]
1471 ----
1472 -- Single field filter
1473 for child in tree:children("tcp.flags") do
1474 print("TCP flags child: " .. tostring(child))
1475 end
1476
1477 -- Multiple field filters
1478 for child in tree:children({"tcp.port", "tcp.srcport", "tcp.dstport"}) do
1479 print("TCP port child: " .. tostring(child))
1480 end
1481 ----
1482
1483 Enable recursive iteration to traverse the entire subtree in depth-first order:
1484 [source,lua]
1485 ----
1486 -- Recursive iteration without filter
1487 for child in tree:children(nil, true) do
1488 print("Descendant: " .. tostring(child))
1489 end
1490
1491 -- Recursive iteration with field filter
1492 for child in tree:children("tcp.flags", true) do
1493 print("TCP flags anywhere in subtree: " .. tostring(child))
1494 end
1495 ----
1496
1497 When using recursive mode with filters, the iterator searches through all descendants
1498 even if parent nodes don't match the filter, ensuring no matching children are missed.
1499
1500 IMPORTANT: Field extractors must still be created for the fields you want to iterate over.
1501 Wireshark optimizes dissection by only creating tree items for fields that are explicitly
1502 requested through field extractors, display filters, or taps. Without proper field extractors,
1503 the fields may not exist in the dissection tree and will not be found by this iterator.
1504
1505 Example of proper field extractor setup:
1506 [source,lua]
1507 ----
1508 -- Define field extractors first
1509 local tcp_flags_extractor = Field.new("tcp.flags")
1510 local tcp_port_extractor = Field.new("tcp.port")
1511
1512 -- Then use tree navigation (extractors ensure fields exist in tree)
1513 for child in tree:children("tcp.flags") do
1514 local field_info = child:get_field_info()
1515 print("TCP Flags:", field_info.value)
1516 end
1517 ----
1518 @since 4.7.0
1519 */
1520
1521#define WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2 2 /* Optional field name(s) to filter by (string or table of strings). */
1522#define WSLUA_OPTARG_TreeItem_children_RECURSIVE3 3 /* Optional boolean to enable recursive (depth-first) iteration. Default is false. */
1523
1524 /* Retrieve and validate the TreeItem */
1525 TreeItem ti = checkTreeItem(L, 1);
1526 if (!ti)
1527 return 0;
1528
1529 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_children_RECURSIVE3 &&
1530 !lua_isnil(L, WSLUA_OPTARG_TreeItem_children_RECURSIVE)(lua_type(L, (3)) == 0) &&
1531 !lua_isboolean(L, WSLUA_OPTARG_TreeItem_children_RECURSIVE)(lua_type(L, (3)) == 1)) {
1532 luaL_error(L, "TreeItem:children() recursive argument must be a boolean");
1533 return 0;
1534 }
1535
1536 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2 &&
1537 !lua_isnil(L, WSLUA_OPTARG_TreeItem_children_FIELD_FILTER)(lua_type(L, (2)) == 0)) {
1538 int filter_arg = WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2;
1539
1540 if (lua_type(L, filter_arg) != LUA_TSTRING4 && !lua_istable(L, filter_arg)(lua_type(L, (filter_arg)) == 5)) {
1541 luaL_error(L, "TreeItem:children() field filter must be a string or table of strings");
1542 return 0;
1543 }
1544
1545 if (lua_istable(L, filter_arg)(lua_type(L, (filter_arg)) == 5)) {
1546 int table_len = (int)lua_rawlen(L, filter_arg);
1547 for (int i = 0; i < table_len; i++) {
1548 lua_rawgeti(L, filter_arg, i + 1);
1549 if (lua_type(L, -1) != LUA_TSTRING4) {
1550 luaL_error(L, "TreeItem:children() field filter table entries must be strings");
1551 return 0;
1552 }
1553 lua_pop(L, 1)lua_settop(L, -(1)-1);
1554 }
1555 }
1556 }
1557
1558 proto_node *first_child = NULL((void*)0);
1559
1560 if (ti->tree) {
1561 /* Get the first child from the tree's linked list */
1562 first_child = ((proto_node *)ti->tree)->first_child;
1563 }
1564
1565 /* Create the iterator state userdata that will be used by the iterator closure */
1566 /* This userdata will be garbage collected when the iterator is no longer referenced */
1567 TreeItem_iterator_state *state = (TreeItem_iterator_state *)lua_newuserdata(L, sizeof(TreeItem_iterator_state))lua_newuserdatauv(L,sizeof(TreeItem_iterator_state),1);
1568
1569 /* Initialize all state fields to safe defaults */
1570 state->current_node = first_child; /* Start with first child */
1571 state->field_filters = NULL((void*)0); /* No filters by default */
1572 state->num_filters = 0;
1573 state->recursive = false0; /* Non-recursive by default */
1574 state->stack = NULL((void*)0); /* Stack only allocated if recursive */
1575 state->stack_size = 0;
1576 state->stack_capacity = 0;
1577
1578 /* Set up garbage collection metatable for the state userdata */
1579 /* This ensures proper cleanup when iterator is no longer referenced */
1580 lua_newtable(L)lua_createtable(L, 0, 0); /* Create metatable */
1581 lua_pushcfunction(L, TreeItem_iterator_state_gc)lua_pushcclosure(L, (TreeItem_iterator_state_gc), 0);
1582 lua_setfield(L, -2, "__gc"); /* Set __gc metamethod */
1583 lua_setmetatable(L, -2); /* Apply metatable to userdata */
1584
1585 /* Check for recursive parameter (argument 3) */
1586 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_children_RECURSIVE3 &&
1587 !lua_isnil(L, WSLUA_OPTARG_TreeItem_children_RECURSIVE)(lua_type(L, (3)) == 0)) {
1588 /* Convert Lua boolean to C bool */
1589 state->recursive = lua_toboolean(L, WSLUA_OPTARG_TreeItem_children_RECURSIVE3);
1590 }
1591
1592 /* Check if filter argument (argument 2) is provided */
1593 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2 &&
1594 !lua_isnil(L, WSLUA_OPTARG_TreeItem_children_FIELD_FILTER)(lua_type(L, (2)) == 0)) {
1595 int filter_arg = WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2;
1596
1597 if (lua_type(L, filter_arg) == LUA_TSTRING4) {
1598 /* Single filter string - allocate array of size 1 */
1599 state->num_filters = 1;
1600 state->field_filters = (char **)g_malloc(sizeof(char *));
1601 /* Duplicate the string (Lua string becomes C string copy) */
1602 state->field_filters[0] = g_strdup(lua_tostring(L, filter_arg))g_strdup_inline (lua_tolstring(L, (filter_arg), ((void*)0)));
1603 } else if (lua_istable(L, filter_arg)(lua_type(L, (filter_arg)) == 5)) {
1604 /* Table of filter strings - extract all strings from table */
1605 int table_len = (int)lua_rawlen(L, filter_arg);
1606 state->num_filters = table_len;
1607 state->field_filters = (char **)g_malloc(sizeof(char *) * table_len);
1608
1609 /* Iterate through Lua table (1-based indexing) */
1610 for (int i = 0; i < table_len; i++) {
1611 lua_rawgeti(L, filter_arg, i + 1); /* Get table[i+1] */
1612 /* Valid string entry - duplicate it */
1613 state->field_filters[i] = g_strdup(lua_tostring(L, -1))g_strdup_inline (lua_tolstring(L, (-1), ((void*)0)));
1614 lua_pop(L, 1)lua_settop(L, -(1)-1); /* Remove the value from stack */
1615 }
1616 }
1617 /* If neither string nor table, filters remain NULL (no filtering) */
1618 }
1619
1620 /* Push the iterator function as a closure with state as upvalue */
1621 /* The state userdata is kept alive as long as the closure exists */
1622 lua_pushcclosure(L, TreeItem_children_iterator, 1);
1623
1624 WSLUA_RETURN(1)return (1); /* An iterator function for use in Lua for loops. */
1625}
1626
1627WSLUA_METHODstatic int TreeItem_get_field_info(lua_State *L) {
1628 /* Returns the FieldInfo object associated with this tree item.
1629
1630 Returns a FieldInfo object that provides access to the underlying field
1631 information including name, abbreviated name, type, value, data offset,
1632 length, and other protocol field properties.
1633
1634 This is particularly useful for extracting actual field values and
1635 metadata from tree items during packet analysis.
1636
1637 [source,lua]
1638 ----
1639 for child in tree:children() do
1640 local field_info = child:get_field_info()
1641 if field_info then
1642 print("Field name: " .. field_info.name)
1643 print("Field abbrev: " .. field_info.abbrev)
1644 print("Field type: " .. field_info.type)
1645 print("Field value: " .. tostring(field_info.value))
1646 print("Field offset: " .. field_info.offset)
1647 print("Field len: " .. field_info.len)
1648 else
1649 print("No field info (text-only or generated item)")
1650 end
1651 end
1652 ----
1653
1654 NOTE: Field extractors are still required to ensure fields exist in the dissection tree.
1655 This method only provides access to field information for tree items that already exist.
1656
1657 @since 4.7.0
1658 */
1659
1660 /* Retrieve and validate the TreeItem */
1661 TreeItem ti = checkTreeItem(L, 1);
1662 if (!ti)
1663 return 0;
1664
1665 field_info *finfo = NULL((void*)0);
1666
1667 /* Get field_info from the proto_item */
1668 if (ti->item) {
1669 /* Cast proto_item to proto_node to access finfo member */
1670 proto_node *node = (proto_node *)ti->item;
1671 finfo = node->finfo; /* May be NULL for text-only tree items */
1672 }
1673
1674 if (finfo) {
1675 /* Valid field_info exists - create and push FieldInfo Lua object */
1676 /* This makes all field properties accessible from Lua */
1677 push_FieldInfo(L, finfo);
1678 } else {
1679 /* No field_info - this is a text-only tree item or generated content */
1680 lua_pushnil(L);
1681 }
1682
1683 WSLUA_RETURN(1)return (1); /* The FieldInfo object, or nil if not available. */
1684}
1685
1686WSLUA_METAMETHODstatic int TreeItem__tostring(lua_State* L) {
1687 /* Returns string debug information about the <<lua_class_TreeItem,`TreeItem`>>. */
1688 TreeItem ti = toTreeItem(L,1);
1689
1690 if (ti) {
1691 lua_pushfstring(L,
1692 "TreeItem: expired=%s, has item=%s, has subtree=%s, they are %sthe same",
1693 ti->expired ? "true" : "false",
1694 ti->item ? "true" : "false",
1695 ti->tree ? "true" : "false",
1696 (ti->tree == ti->item) ? "" : "not ");
1697 }
1698 else {
1699 lua_pushstring(L, "No TreeItem object!");
1700 }
1701
1702 return 1;
1703}
1704
1705/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
1706static int TreeItem__gc(lua_State* L) {
1707 TreeItem ti = toTreeItem(L,1);
1708 if (!ti) return 0;
1709 if (!ti->expired)
1710 ti->expired = true1;
1711 else
1712 g_free(ti);
1713 return 0;
1714}
1715
1716WSLUA_ATTRIBUTESstatic const wslua_attribute_table TreeItem_attributes[] = {
1717 WSLUA_ATTRIBUTE_RWREG(TreeItem,generated){ "generated", TreeItem_get_generated, TreeItem_set_generated
}
,
1718 WSLUA_ATTRIBUTE_RWREG(TreeItem,hidden){ "hidden", TreeItem_get_hidden, TreeItem_set_hidden },
1719 WSLUA_ATTRIBUTE_RWREG(TreeItem,len){ "len", TreeItem_get_len, TreeItem_set_len },
1720 WSLUA_ATTRIBUTE_RWREG(TreeItem,text){ "text", TreeItem_get_text, TreeItem_set_text },
1721 WSLUA_ATTRIBUTE_ROREG(TreeItem,visible){ "visible", TreeItem_get_visible, ((void*)0) },
1722 { NULL((void*)0), NULL((void*)0), NULL((void*)0) }
1723};
1724
1725WSLUA_METHODSstatic const luaL_Reg TreeItem_methods[] = {
1726 WSLUA_CLASS_FNREG(TreeItem, add_packet_field){ "add_packet_field", TreeItem_add_packet_field },
1727 WSLUA_CLASS_FNREG(TreeItem, add){ "add", TreeItem_add },
1728 WSLUA_CLASS_FNREG(TreeItem, add_le){ "add_le", TreeItem_add_le },
1729 WSLUA_CLASS_FNREG(TreeItem, set_text){ "set_text", TreeItem_set_text },
1730 WSLUA_CLASS_FNREG(TreeItem, append_text){ "append_text", TreeItem_append_text },
1731 WSLUA_CLASS_FNREG(TreeItem, prepend_text){ "prepend_text", TreeItem_prepend_text },
1732 WSLUA_CLASS_FNREG(TreeItem, add_expert_info){ "add_expert_info", TreeItem_add_expert_info },
1733 WSLUA_CLASS_FNREG(TreeItem, add_proto_expert_info){ "add_proto_expert_info", TreeItem_add_proto_expert_info },
1734 WSLUA_CLASS_FNREG(TreeItem, add_tvb_expert_info){ "add_tvb_expert_info", TreeItem_add_tvb_expert_info },
1735 WSLUA_CLASS_FNREG(TreeItem, set_generated){ "set_generated", TreeItem_set_generated },
1736 WSLUA_CLASS_FNREG(TreeItem, set_hidden){ "set_hidden", TreeItem_set_hidden },
1737 WSLUA_CLASS_FNREG(TreeItem, set_len){ "set_len", TreeItem_set_len },
1738 WSLUA_CLASS_FNREG(TreeItem, referenced){ "referenced", TreeItem_referenced },
1739 WSLUA_CLASS_FNREG(TreeItem, get_child_count){ "get_child_count", TreeItem_get_child_count },
1740 WSLUA_CLASS_FNREG(TreeItem, get_parent){ "get_parent", TreeItem_get_parent },
1741 WSLUA_CLASS_FNREG(TreeItem, get_child){ "get_child", TreeItem_get_child },
1742 WSLUA_CLASS_FNREG(TreeItem, children){ "children", TreeItem_children },
1743 WSLUA_CLASS_FNREG(TreeItem, get_field_info){ "get_field_info", TreeItem_get_field_info },
1744 {NULL((void*)0), NULL((void*)0)}};
1745
1746WSLUA_METAstatic const luaL_Reg TreeItem_meta[] = {
1747 WSLUA_CLASS_MTREG(TreeItem,tostring){ "__" "tostring", TreeItem__tostring },
1748 { NULL((void*)0), NULL((void*)0) }
1749};
1750
1751int TreeItem_register(lua_State *L) {
1752 int* etts[] = { &wslua_ett };
1753 wslua_ett = -1; /* Reset to support reload Lua plugins */
1754 WSLUA_REGISTER_CLASS_WITH_ATTRS(TreeItem){ const wslua_class TreeItem_class = { .name = "TreeItem", .class_methods
= TreeItem_methods, .class_meta = TreeItem_meta, .instance_methods
= TreeItem_methods, .instance_meta = TreeItem_meta, .attrs =
TreeItem_attributes }; wslua_register_class(L, &TreeItem_class
); (lua_getfield(L, (-1000000 - 1000), ("TreeItem"))); lua_pushcclosure
(L, (TreeItem__gc), 0); lua_setfield(L, -2, "__gc"); lua_settop
(L, -(1)-1); }
;
1755 if (outstanding_TreeItem != NULL((void*)0)) {
1756 g_ptr_array_unref(outstanding_TreeItem);
1757 }
1758 outstanding_TreeItem = g_ptr_array_new();
1759 proto_register_subtree_array(etts,1);
1760 return 0;
1761}
1762
1763/*
1764 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1765 *
1766 * Local variables:
1767 * c-basic-offset: 4
1768 * tab-width: 8
1769 * indent-tabs-mode: nil
1770 * End:
1771 *
1772 * vi: set shiftwidth=4 tabstop=8 expandtab:
1773 * :indentSize=4:tabSize=8:noTabs=true:
1774 */