Bug Summary

File:builds/wireshark/wireshark/wiretap/procmon.c
Warning:line 792, column 32
Use of memory after it is freed

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 procmon.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/libxml2 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D wiretap_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -I /builds/wireshark/wireshark/build/wiretap -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-03-100346-3621-1 -x c /builds/wireshark/wireshark/wiretap/procmon.c
1/** procmon.c
2 *
3 * Implements reading of MS Procmon files
4 * Used a lot of information from https://github.com/eronnen/procmon-parser
5 *
6 * Wiretap Library
7 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12#include "config.h"
13#define WS_LOG_DOMAIN"Wiretap" LOG_DOMAIN_WIRETAP"Wiretap"
14
15#include "procmon.h"
16#include "file_wrappers.h"
17#include "wtap_module.h"
18#include "pcapng_module.h"
19
20#include <wsutil/buffer.h>
21
22// To do:
23// - Figure out module timestamps
24// - Read the ports array? Is there any advantage to doing that vs our built in
25// port number resolution?
26
27#pragma pack(push,1)
28typedef struct procmon_header_s {
29 uint32_t signature; // Magic Signature - 'PML_'
30 uint32_t version; // Version of the PML file. 9 in the current version.
31 uint32_t system_bitness; // System bitness: 1 if the system is 64 bit, 0 otherwise.
32 uint16_t computer_name[16]; // Name of the computer (that did the capture).
33 uint16_t system_root_path[260]; // System root path (e.g. "C:\Windows").
34 uint32_t num_events; // Total number of events in the log file.
35 uint64_t unused; // ? (seems to be unused)
36 uint64_t start_events_offset; // File offset to the start of the events array.
37 uint64_t event_offsets_array_offset;// File offset to an array of offsets to all the events.
38 uint64_t process_array_offset; // File offset to the array of processes.
39 uint64_t string_array_offset; // File offset to the array of strings.
40 uint64_t icon_array_offset; // File offset to the icons array.
41 uint64_t maximum_user_address; // SYSTEM_INFO.lpMaximumApplicationAddress: Maximum User Address
42 uint32_t os_version_info_size; // OSVERSIONINFOEXW.dwOSVersionInfoSize: sizeof(OSVERSIONINFOEXW)
43 uint32_t major_version; // OSVERSIONINFOEXW.dwMajorVersion: Major version number of the operating system.
44 uint32_t minor_version; // OSVERSIONINFOEXW.dwMinorVersion: Minor version number of the operating system.
45 uint32_t build_number; // OSVERSIONINFOEXW.dwBuildNumber: Build number of the operating system.
46 uint32_t platform_id; // OSVERSIONINFOEXW.dwPlatformId: Operating system platform.
47 uint16_t csd_version[128]; // OSVERSIONINFOEXW.szCSDVersion: Indicates the latest Service Pack installed.
48 uint16_t service_pack_major; // OSVERSIONINFOEXW.wServicePackMajor: Major version number of the latest Service Pack.
49 uint16_t service_pack_minor; // OSVERSIONINFOEXW.wServicePackMinor: Minor version number of the latest Service Pack.
50 uint16_t suite_mask; // OSVERSIONINFOEXW.wSuiteMask: Bit mask that identifies the product suites available.
51 uint8_t product_type; // OSVERSIONINFOEXW.wProductType: Additional information about the system.
52 uint8_t version_reserved; // OSVERSIONINFOEXW.wReserved: Reserved for future use.
53 uint32_t num_processors; // SYSTEM_INFO.dwNumberOfProcessors: Number of logical processors.
54 uint64_t total_physical_memory; // MEMORYSTATUSEX.ullTotalPhys: Total physical memory (in bytes).
55 uint64_t start_events_offset_dup; // File offset to the start of the events array (again).
56 uint64_t host_port_array_offset; // File offset to hosts and ports arrays.
57} procmon_header_t;
58
59typedef enum {
60 PROCMON_EVENT_TYPE_UNKNOWN = 0,
61 PROCMON_EVENT_TYPE_PROCESS = 1,
62 PROCMON_EVENT_TYPE_REGISTRY = 2,
63 PROCMON_EVENT_TYPE_FILE_SYSTEM = 3,
64 PROCMON_EVENT_TYPE_PROFILING = 4,
65 PROCMON_EVENT_TYPE_NETWORK = 5,
66} procmon_event_class_type_t;
67
68typedef struct procmon_event_header_s {
69 uint32_t process_index; // The index to the process of the event.
70 uint32_t thread_id; // Thread Id.
71 uint32_t event_class; // Event class (of type procmon_event_class_type_t)
72 uint16_t operation_type; // Operation type (dependent on the event class)
73 uint8_t unknown[6]; // Unknown
74 uint64_t duration; // Duration of the operation in 100 nanoseconds interval.
75 uint64_t timestamp; // The time when the event was captured (in FILETIME format)
76 uint32_t event_result; // The value of the event result.
77 uint16_t stack_trace_depth; // The depth of the captured stack trace.
78 uint16_t unknown3; // Unknown
79 uint32_t details_size; // The size of the specific detail structure (contains path and other details)
80 uint32_t extra_details_offset; // The offset from the start of the event to extra detail structure (not necessarily continuous with this structure).
81
82} procmon_event_header_t;
83#pragma pack(pop)
84
85typedef struct {
86 uint32_t process_index;
87 uint32_t process_id;
88 uint32_t parent_process_id;
89 uint32_t parent_process_index;
90 uint64_t authentication_id;
91 uint32_t session_number;
92 uint32_t unknown1;
93 uint64_t start_time; // FILETIME
94 uint64_t end_time; // FILETIME
95 uint32_t is_virtualized;
96 uint32_t is_64_bit;
97 uint32_t integrity_si;
98 uint32_t user_name_si;
99 uint32_t process_name_si;
100 uint32_t image_path_si;
101 uint32_t command_line_si;
102 uint32_t company_si;
103 uint32_t version_si;
104 uint32_t description_si;
105 uint32_t icon_index_big;
106 uint32_t icon_index_small;
107} procmon_raw_process_t;
108
109typedef struct {
110 uint32_t unknown1;
111 uint32_t base_address;
112 uint32_t size;
113 uint32_t image_path_si;
114 uint32_t version_si;
115 uint32_t company_si;
116 uint32_t description_si;
117 uint32_t timestamp;
118 uint64_t unknown2[3];
119} procmon_raw_module_32_t;
120
121typedef struct {
122 uint64_t unknown1;
123 uint64_t base_address;
124 uint32_t size;
125 uint32_t image_path_si;
126 uint32_t version_si;
127 uint32_t company_si;
128 uint32_t description_si;
129 uint32_t timestamp;
130 uint64_t unknown2[3];
131} procmon_raw_module_64_t;
132
133typedef struct {
134 procmon_header_t header;
135 uint32_t *event_offsets;
136 uint32_t cur_event;
137 const char **string_array;
138 size_t string_array_size;
139 uint32_t *process_index_map; /* Map of process index to process array index */
140 size_t process_index_map_size;
141 struct procmon_process_t *process_array;
142 size_t process_array_size;
143} procmon_file_info_t;
144
145#define COMMON_EVENT_STRUCT_SIZE52 52
146// Most of these are arbitrary
147#define MAX_PROCMON_EVENTS(500 * 1000 * 1000) (500 * 1000 * 1000)
148#define MAX_PROCMON_STRINGS(1000 * 1000) (1000 * 1000)
149#define MAX_PROCMON_STRING_LENGTH8192 8192
150#define MAX_PROCMON_PROCESSES(500 * 1000) (500 * 1000)
151#define MAX_PROCMON_MODULES1000 1000
152
153static int procmon_file_type_subtype = -1;
154
155void register_procmon(void);
156
157static void file_info_cleanup(procmon_file_info_t* file_info)
158{
159 g_free(file_info->event_offsets);
160 g_free(file_info->string_array);
161 g_free(file_info->process_index_map);
162 if (file_info->process_array
77.1
Field 'process_array' is non-null
) {
78
Taking true branch
163 for (size_t idx = 0; idx < file_info->process_array_size; idx++) {
79
Loop condition is true. Entering loop body
80
Loop condition is false. Execution continues on line 166
164 g_free(file_info->process_array[idx].modules);
165 }
166 g_free(file_info->process_array);
81
Memory is released
167 }
168 g_free(file_info);
169}
170
171static const char *procmon_string(procmon_file_info_t* file_info, uint32_t str_index)
172{
173 if (str_index >= file_info->string_array_size) {
174 return "<unknown>";
175 }
176 return file_info->string_array[str_index];
177}
178
179static char *procmon_read_string(FILE_T fh, gunichar2 *str_buf, int *err, char **err_info)
180{
181 uint32_t cur_str_size;
182 if (!wtap_read_bytes_or_eof(fh, &cur_str_size, sizeof(cur_str_size), err, err_info))
183 {
184 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 184, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
185 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
186 {
187 // Short read or EOF.
188 *err = 0;
189 g_free(*err_info);
190 *err_info = NULL((void*)0);
191 }
192 return NULL((void*)0);
193 }
194 cur_str_size = GUINT32_FROM_LE(cur_str_size)(((guint32) (cur_str_size)));
195 if (cur_str_size > MAX_PROCMON_STRING_LENGTH8192)
196 {
197 if (file_seek(fh, cur_str_size - MAX_PROCMON_STRING_LENGTH8192, SEEK_CUR1, err) == -1)
198 {
199 ws_debug("Failed to skip excess string data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 199, __func__, "Failed to skip excess string data"); } } while
(0)
;
200 return NULL((void*)0);
201 }
202 ws_debug("Truncating string from %u bytes to %u", cur_str_size, MAX_PROCMON_STRING_LENGTH)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 202, __func__, "Truncating string from %u bytes to %u", cur_str_size
, 8192); } } while (0)
;
203 cur_str_size = MAX_PROCMON_STRING_LENGTH8192;
204 }
205 // XXX Make sure cur_str_size is even?
206 if (!wtap_read_bytes_or_eof(fh, str_buf, cur_str_size, err, err_info))
207 {
208 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 208, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
209 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
210 {
211 // Short read or EOF.
212 *err = 0;
213 g_free(*err_info);
214 *err_info = NULL((void*)0);
215 }
216 return NULL((void*)0);
217 }
218 return g_utf16_to_utf8(str_buf, cur_str_size, NULL((void*)0), NULL((void*)0), NULL((void*)0));
219}
220
221// Read the hosts array. Assume failures here are non-fatal.
222static void procmon_read_hosts(wtap *wth, int64_t host_port_array_offset, int *err, char **err_info)
223{
224 if (!(wth->add_new_ipv4 && wth->add_new_ipv6)) {
225 return;
226 }
227
228 if (file_seek(wth->fh, host_port_array_offset, SEEK_SET0, err) == -1)
229 {
230 ws_debug("Failed to locate procmon hosts+ports data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 230, __func__, "Failed to locate procmon hosts+ports data")
; } } while (0)
;
231 return;
232 }
233 uint32_t num_hosts;
234 if (!wtap_read_bytes_or_eof(wth->fh, &num_hosts, sizeof(num_hosts), err, err_info))
235 {
236 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 236, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
237 return;
238 }
239 num_hosts = GUINT32_FROM_LE(num_hosts)(((guint32) (num_hosts)));
240 if (num_hosts > MAX_PROCMON_STRINGS(1000 * 1000))
241 {
242 ws_debug("Truncating hosts from %u to %u", num_hosts, MAX_PROCMON_STRINGS)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 242, __func__, "Truncating hosts from %u to %u", num_hosts,
(1000 * 1000)); } } while (0)
;
243 num_hosts = MAX_PROCMON_STRINGS(1000 * 1000);
244 }
245 gunichar2 *str_buf = g_new(gunichar2, MAX_PROCMON_STRING_LENGTH)((gunichar2 *) g_malloc_n ((8192), sizeof (gunichar2)));
246 // Procmon appears to use the hosts table to store ASCII representations of
247 // addresses, so skip those.
248 GRegex *numeric_re = g_regex_new("^([0-9.]+|.*:.*)$", (GRegexCompileFlags)(G_REGEX_CASELESS | G_REGEX_RAW | G_REGEX_OPTIMIZE), (GRegexMatchFlags)0, NULL((void*)0));
249 for (unsigned idx = 0; idx < num_hosts; idx++)
250 {
251 ws_in6_addr addr;
252 if (!wtap_read_bytes_or_eof(wth->fh, &addr, sizeof(addr), err, err_info))
253 {
254 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 254, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
255 g_regex_unref(numeric_re);
256 g_free(str_buf);
257 return;
258 }
259 char *name = procmon_read_string(wth->fh, str_buf, err, err_info);
260 if (!name) {
261 continue;
262 }
263 if (g_regex_match(numeric_re, name, (GRegexMatchFlags)0, NULL((void*)0)))
264 {
265 g_free(name);
266 continue;
267 }
268 // The PML format gives us a 16 byte blob with no indication as to
269 // whether or not the blob is a v4 or v6 address. Given that there are
270 // several pingable v6 addresses that end with 12 bytes of zeroes (at
271 // the time of this writing 2600::, 2409::, 2a09::, and 2a11:: are all
272 // pingable), let's assume that all addresses are v6 and ones that end
273 // with 12 bytes of zeroes are also v4.
274 wth->add_new_ipv6(&addr, name, false0);
275 if (!*(uint32_t*)(&addr.bytes[4]) && !*(uint64_t*)(&addr.bytes[8])) {
276 ws_in4_addr v4addr = *(uint32_t *)(&addr.bytes[4]);
277 wth->add_new_ipv4(v4addr, name, false0);
278 }
279 g_free(name);
280 }
281 g_regex_unref(numeric_re);
282 g_free(str_buf);
283}
284
285static bool_Bool procmon_read_event(FILE_T fh, wtap_rec* rec, procmon_file_info_t* file_info, int* err, char** err_info)
286{
287 wtapng_block_t wblock;
288 procmon_event_header_t event_header;
289
290 wblock.rec = rec;
291
292 wblock.block = wtap_block_create(WTAP_BLOCK_FT_SPECIFIC_EVENT);
293
294 wblock.rec->presence_flags = WTAP_HAS_CAP_LEN0x00000002;
295 wblock.rec->tsprec = WTAP_TSPREC_NSEC9;
296
297 /* Read the event header */
298 if (!wtap_read_bytes(fh, &event_header, sizeof event_header, err, err_info)) {
299 ws_debug("Failed to read procmon process index")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 299, __func__, "Failed to read procmon process index"); } }
while (0)
;
300 return false0;
301 }
302
303 /* Append the raw data of the event header */
304 ws_buffer_append(&wblock.rec->data, (const uint8_t*)&event_header, sizeof event_header);
305
306 wblock.rec->presence_flags |= WTAP_HAS_TS0x00000001;
307 filetime_to_nstime(&wblock.rec->ts, GUINT64_FROM_LE(event_header.timestamp)(((guint64) (event_header.timestamp))));
308
309 /* Read stack trace data */
310 uint32_t sizeof_stacktrace = event_header.stack_trace_depth * (file_info->header.system_bitness ? 8 : 4);
311
312 /* Append the size of the stack trace data so the dissector doesn't need to know about system bitness */
313 ws_buffer_append(&wblock.rec->data, (const uint8_t*)&sizeof_stacktrace, sizeof sizeof_stacktrace);
314
315 if (!wtap_read_bytes_buffer(fh, &wblock.rec->data, sizeof_stacktrace, err, err_info)) {
316 ws_debug("Failed to read procmon stack trace data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 316, __func__, "Failed to read procmon stack trace data"); }
} while (0)
;
317 return false0;
318 }
319
320 /* Read detail data */
321 if (!wtap_read_bytes_buffer(fh, &wblock.rec->data, event_header.details_size, err, err_info)) {
322 ws_debug("Failed to read procmon detail data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 322, __func__, "Failed to read procmon detail data"); } } while
(0)
;
323 return false0;
324 }
325
326 if (event_header.extra_details_offset > 0)
327 {
328 int64_t current_offset = file_tell(fh);
329
330 /* The extra details structure surprisingly can be separated from the event structure */
331 int64_t real_details_offset = event_header.extra_details_offset - (COMMON_EVENT_STRUCT_SIZE52 + event_header.details_size + sizeof_stacktrace);
332 if (file_seek(fh, real_details_offset, SEEK_CUR1, err) == -1) {
333 ws_debug("Failed to locate procmon extra details data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 333, __func__, "Failed to locate procmon extra details data"
); } } while (0)
;
334 return false0;
335 }
336 /* However, pass the record data up as if it's consecutive */
337 uint16_t extra_details_stream_size;
338 if (!wtap_read_bytes(fh, &extra_details_stream_size, sizeof extra_details_stream_size, err, err_info)) {
339 ws_debug("Failed to read procmon extra details offset")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 339, __func__, "Failed to read procmon extra details offset"
); } } while (0)
;
340 return false0;
341 }
342 ws_buffer_append(&wblock.rec->data, (const uint8_t*)&extra_details_stream_size, sizeof extra_details_stream_size);
343
344 if (!wtap_read_bytes_buffer(fh, &wblock.rec->data, extra_details_stream_size, err, err_info)) {
345 ws_debug("Failed to read procmon extra detail data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 345, __func__, "Failed to read procmon extra detail data");
} } while (0)
;
346 return false0;
347 }
348
349 /* If the extra data doesn't immediately follow the other data */
350 if (real_details_offset != 0)
351 {
352 if (file_seek(fh, current_offset, SEEK_SET0, err) == -1) {
353 ws_debug("Failed to restore procmon event data location")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 353, __func__, "Failed to restore procmon event data location"
); } } while (0)
;
354 return false0;
355 }
356 }
357 }
358
359 /*
360 * We return these to the caller in procmon_read().
361 */
362 wtap_setup_ft_specific_event_rec(wblock.rec, procmon_file_type_subtype, event_header.event_class);
363 wblock.rec->rec_header.ft_specific_header.record_len = (uint32_t)ws_buffer_length(&wblock.rec->data);
364 wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.process_index_map = file_info->process_index_map;
365 wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.process_index_map_size = file_info->process_index_map_size;
366 wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.process_array = file_info->process_array;
367 wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.process_array_size = file_info->process_array_size;
368 wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.system_bitness = (file_info->header.system_bitness != 0);
369 wblock.internal = false0;
370
371 /*
372 * We want dissectors (particularly packet_frame) to be able to
373 * access packet comments and whatnot that are in the block. wblock->block
374 * will be unref'd by procmon_seek_read(), so move the block to where
375 * dissectors can find it.
376 */
377 wblock.rec->block = wblock.block;
378 wblock.block = NULL((void*)0);
379 return true1;
380}
381
382static bool_Bool procmon_read(wtap *wth, wtap_rec *rec,
383 int *err, char **err_info, int64_t *data_offset)
384{
385 procmon_file_info_t* file_info = (procmon_file_info_t*)wth->priv;
386
387 // file.c and strato.c call wtap_set_cb_new_ipv{4,6} after calling
388 // wtap_open_offline, so read our hosts array here.
389 if (file_info->cur_event == 0) {
390 procmon_read_hosts(wth, file_info->header.host_port_array_offset, err, err_info);
391 }
392
393 *data_offset = file_info->event_offsets[file_info->cur_event];
394 ws_noisy("file offset is %" PRId64 " array offset is %" PRId64, file_tell(wth->fh), *data_offset)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/procmon.c"
, 394, __func__, "file offset is %" "l" "d" " array offset is %"
"l" "d", file_tell(wth->fh), *data_offset); } } while (0)
;
395
396 if (file_seek(wth->fh, *data_offset, SEEK_SET0, err) == -1)
397 {
398 ws_debug("Failed to seek to event %u at offsets %" PRId64, file_info->cur_event, *data_offset)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 398, __func__, "Failed to seek to event %u at offsets %" "l"
"d", file_info->cur_event, *data_offset); } } while (0)
;
399 return false0;
400 }
401
402 /* Stop processing once offset reaches past events */
403 if (file_info->cur_event >= file_info->header.num_events)
404 {
405 ws_debug("end of events")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 405, __func__, "end of events"); } } while (0)
;
406 return false0;
407 }
408 file_info->cur_event++;
409
410 // if (*data_offset+COMMON_EVENT_STRUCT_SIZE >= (int64_t)file_info->header.event_offsets_array_offset) {
411 // *err = WTAP_ERR_BAD_FILE;
412 // *err_info = ws_strdup_printf("procmon: Not enough room for event content at offset %" PRIi64, *data_offset);
413 // return false;
414 // }
415
416 return procmon_read_event(wth->fh, rec, file_info, err, err_info);
417}
418
419static bool_Bool procmon_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec,
420 int *err, char **err_info)
421{
422 procmon_file_info_t* file_info = (procmon_file_info_t*)wth->priv;
423
424 /* seek to the right file position */
425 if (file_seek(wth->random_fh, seek_off, SEEK_SET0, err) < 0) {
426 return false0; /* Seek error */
427 }
428 ws_noisy("reading at offset %" PRIu64, seek_off)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/procmon.c"
, 428, __func__, "reading at offset %" "l" "u", seek_off); } }
while (0)
;
429
430 return procmon_read_event(wth->random_fh, rec, file_info, err, err_info);
431}
432
433static const uint8_t procmon_magic[] = { 'P', 'M', 'L', '_' };
434
435wtap_open_return_val procmon_open(wtap *wth, int *err, char **err_info)
436{
437 procmon_file_info_t* file_info = g_new0(procmon_file_info_t, 1)((procmon_file_info_t *) g_malloc0_n ((1), sizeof (procmon_file_info_t
)))
;
438 procmon_header_t* header = &file_info->header;
439
440 ws_debug("opening file")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 440, __func__, "opening file"); } } while (0)
;
1
Taking true branch
2
Loop condition is false. Exiting loop
441 /*
442 * First, try to read the procmon header.
443 */
444 if (!wtap_read_bytes_or_eof(wth->fh, header, sizeof(procmon_header_t), err, err_info))
3
Assuming the condition is false
4
Taking false branch
445 {
446 file_info_cleanup(file_info);
447 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 447, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
448 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) {
449 /*
450 * Short read or EOF.
451 *
452 * We're reading this as part of an open, so
453 * the file is too short to be a procmon file.
454 */
455 *err = 0;
456 g_free(*err_info);
457 *err_info = NULL((void*)0);
458 }
459 return WTAP_OPEN_NOT_MINE;
460 }
461
462 if (memcmp(&header->signature, procmon_magic, sizeof(procmon_magic)))
5
Assuming the condition is false
6
Taking false branch
463 {
464 file_info_cleanup(file_info);
465 return WTAP_OPEN_NOT_MINE;
466 }
467
468#if G_BYTE_ORDER1234 == G_BIG_ENDIAN4321
469 header->version = GUINT32_SWAP_LE_BE(header->version)(((guint32) ( (((guint32) (header->version) & (guint32
) 0x000000ffU) << 24) | (((guint32) (header->version
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header
->version) & (guint32) 0x00ff0000U) >> 8) | (((guint32
) (header->version) & (guint32) 0xff000000U) >> 24
))))
;
470 header->system_bitness = GUINT32_SWAP_LE_BE(header->system_bitness)(((guint32) ( (((guint32) (header->system_bitness) & (
guint32) 0x000000ffU) << 24) | (((guint32) (header->
system_bitness) & (guint32) 0x0000ff00U) << 8) | ((
(guint32) (header->system_bitness) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (header->system_bitness) &
(guint32) 0xff000000U) >> 24))))
;
471 header->num_events = GUINT32_SWAP_LE_BE(header->num_events)(((guint32) ( (((guint32) (header->num_events) & (guint32
) 0x000000ffU) << 24) | (((guint32) (header->num_events
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header
->num_events) & (guint32) 0x00ff0000U) >> 8) | (
((guint32) (header->num_events) & (guint32) 0xff000000U
) >> 24))))
;
472 header->start_events_offset = GUINT64_SWAP_LE_BE(header->start_events_offset)(((guint64) ( (((guint64) (header->start_events_offset) &
(guint64) (0x00000000000000ffUL)) << 56) | (((guint64)
(header->start_events_offset) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->start_events_offset
) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64
) (header->start_events_offset) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->start_events_offset)
& (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (header->start_events_offset) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->start_events_offset
) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64
) (header->start_events_offset) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
473 header->event_offsets_array_offset = GUINT64_SWAP_LE_BE(header->event_offsets_array_offset)(((guint64) ( (((guint64) (header->event_offsets_array_offset
) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64
) (header->event_offsets_array_offset) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->event_offsets_array_offset
) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64
) (header->event_offsets_array_offset) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->event_offsets_array_offset
) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (header->event_offsets_array_offset) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->event_offsets_array_offset
) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64
) (header->event_offsets_array_offset) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
474 header->process_array_offset = GUINT64_SWAP_LE_BE(header->process_array_offset)(((guint64) ( (((guint64) (header->process_array_offset) &
(guint64) (0x00000000000000ffUL)) << 56) | (((guint64)
(header->process_array_offset) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->process_array_offset
) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64
) (header->process_array_offset) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->process_array_offset
) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (header->process_array_offset) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->process_array_offset
) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64
) (header->process_array_offset) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
475 header->string_array_offset = GUINT64_SWAP_LE_BE(header->string_array_offset)(((guint64) ( (((guint64) (header->string_array_offset) &
(guint64) (0x00000000000000ffUL)) << 56) | (((guint64)
(header->string_array_offset) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->string_array_offset
) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64
) (header->string_array_offset) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->string_array_offset)
& (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (header->string_array_offset) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->string_array_offset
) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64
) (header->string_array_offset) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
476 header->icon_array_offset = GUINT64_SWAP_LE_BE(header->icon_array_offset)(((guint64) ( (((guint64) (header->icon_array_offset) &
(guint64) (0x00000000000000ffUL)) << 56) | (((guint64)
(header->icon_array_offset) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->icon_array_offset) &
(guint64) (0x0000000000ff0000UL)) << 24) | (((guint64)
(header->icon_array_offset) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->icon_array_offset) &
(guint64) (0x000000ff00000000UL)) >> 8) | (((guint64) (
header->icon_array_offset) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->icon_array_offset) &
(guint64) (0x00ff000000000000UL)) >> 40) | (((guint64)
(header->icon_array_offset) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
477 header->maximum_user_address = GUINT64_SWAP_LE_BE(header->maximum_user_address)(((guint64) ( (((guint64) (header->maximum_user_address) &
(guint64) (0x00000000000000ffUL)) << 56) | (((guint64)
(header->maximum_user_address) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->maximum_user_address
) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64
) (header->maximum_user_address) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->maximum_user_address
) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (header->maximum_user_address) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->maximum_user_address
) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64
) (header->maximum_user_address) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
478 header->os_version_info_size = GUINT32_SWAP_LE_BE(header->os_version_info_size)(((guint32) ( (((guint32) (header->os_version_info_size) &
(guint32) 0x000000ffU) << 24) | (((guint32) (header->
os_version_info_size) & (guint32) 0x0000ff00U) << 8
) | (((guint32) (header->os_version_info_size) & (guint32
) 0x00ff0000U) >> 8) | (((guint32) (header->os_version_info_size
) & (guint32) 0xff000000U) >> 24))))
;
479 header->major_version = GUINT32_SWAP_LE_BE(header->major_version)(((guint32) ( (((guint32) (header->major_version) & (guint32
) 0x000000ffU) << 24) | (((guint32) (header->major_version
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header
->major_version) & (guint32) 0x00ff0000U) >> 8) |
(((guint32) (header->major_version) & (guint32) 0xff000000U
) >> 24))))
;
480 header->minor_version = GUINT32_SWAP_LE_BE(header->minor_version)(((guint32) ( (((guint32) (header->minor_version) & (guint32
) 0x000000ffU) << 24) | (((guint32) (header->minor_version
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header
->minor_version) & (guint32) 0x00ff0000U) >> 8) |
(((guint32) (header->minor_version) & (guint32) 0xff000000U
) >> 24))))
;
481 header->build_number = GUINT32_SWAP_LE_BE(header->build_number)(((guint32) ( (((guint32) (header->build_number) & (guint32
) 0x000000ffU) << 24) | (((guint32) (header->build_number
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header
->build_number) & (guint32) 0x00ff0000U) >> 8) |
(((guint32) (header->build_number) & (guint32) 0xff000000U
) >> 24))))
;
482 header->platform_id = GUINT32_SWAP_LE_BE(header->platform_id)(((guint32) ( (((guint32) (header->platform_id) & (guint32
) 0x000000ffU) << 24) | (((guint32) (header->platform_id
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header
->platform_id) & (guint32) 0x00ff0000U) >> 8) | (
((guint32) (header->platform_id) & (guint32) 0xff000000U
) >> 24))))
;
483 header->service_pack_major = GUINT16_SWAP_LE_BE(header->service_pack_major)(((guint16) ( (guint16) ((guint16) (header->service_pack_major
) >> 8) | (guint16) ((guint16) (header->service_pack_major
) << 8))))
;
484 header->service_pack_minor = GUINT16_SWAP_LE_BE(header->service_pack_minor)(((guint16) ( (guint16) ((guint16) (header->service_pack_minor
) >> 8) | (guint16) ((guint16) (header->service_pack_minor
) << 8))))
;
485 header->suite_mask = GUINT16_SWAP_LE_BE(header->suite_mask)(((guint16) ( (guint16) ((guint16) (header->suite_mask) >>
8) | (guint16) ((guint16) (header->suite_mask) << 8
))))
;
486 header->num_processors = GUINT32_SWAP_LE_BE(header->num_processors)(((guint32) ( (((guint32) (header->num_processors) & (
guint32) 0x000000ffU) << 24) | (((guint32) (header->
num_processors) & (guint32) 0x0000ff00U) << 8) | ((
(guint32) (header->num_processors) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (header->num_processors) &
(guint32) 0xff000000U) >> 24))))
;
487 header->total_physical_memory = GUINT64_SWAP_LE_BE(header->total_physical_memory)(((guint64) ( (((guint64) (header->total_physical_memory) &
(guint64) (0x00000000000000ffUL)) << 56) | (((guint64)
(header->total_physical_memory) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->total_physical_memory
) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64
) (header->total_physical_memory) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->total_physical_memory
) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (header->total_physical_memory) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->total_physical_memory
) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64
) (header->total_physical_memory) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
488 header->start_events_offset_dup = GUINT64_SWAP_LE_BE(header->start_events_offset_dup)(((guint64) ( (((guint64) (header->start_events_offset_dup
) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64
) (header->start_events_offset_dup) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->start_events_offset_dup
) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64
) (header->start_events_offset_dup) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->start_events_offset_dup
) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (header->start_events_offset_dup) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->start_events_offset_dup
) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64
) (header->start_events_offset_dup) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
489 header->host_port_array_offset = GUINT64_SWAP_LE_BE(header->host_port_array_offset)(((guint64) ( (((guint64) (header->host_port_array_offset)
& (guint64) (0x00000000000000ffUL)) << 56) | (((guint64
) (header->host_port_array_offset) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (header->host_port_array_offset
) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64
) (header->host_port_array_offset) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (header->host_port_array_offset
) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (header->host_port_array_offset) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (header->host_port_array_offset
) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64
) (header->host_port_array_offset) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
490#endif
491
492 if (header->num_events > MAX_PROCMON_EVENTS(500 * 1000 * 1000)) {
7
Assuming the condition is false
8
Taking false branch
493 ws_debug("Truncating events from %u to %u", header->num_events, MAX_PROCMON_EVENTS)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 493, __func__, "Truncating events from %u to %u", header->
num_events, (500 * 1000 * 1000)); } } while (0)
;
494 header->num_events = MAX_PROCMON_EVENTS(500 * 1000 * 1000);
495 }
496
497 // Read the event offsets array, which we use in procmon_read(). It's not clear
498 // if we really need this; in a test capture here the offsets in the array were
499 // identical to the file positions we end up with if we just read sequentially.
500 if (file_seek(wth->fh, header->event_offsets_array_offset, SEEK_SET0, err) == -1)
9
Assuming the condition is false
10
Taking false branch
501 {
502 file_info_cleanup(file_info);
503 ws_debug("Failed to locate event offsets data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 503, __func__, "Failed to locate event offsets data"); } } while
(0)
;
504 return WTAP_OPEN_NOT_MINE;
505 }
506 file_info->event_offsets = g_new(uint32_t, header->num_events)((uint32_t *) g_malloc_n ((header->num_events), sizeof (uint32_t
)))
;
507 for (unsigned idx = 0; idx
10.1
'idx' is < field 'num_events'
< header->num_events
; idx++) {
11
Loop condition is true. Entering loop body
16
Assuming 'idx' is >= field 'num_events'
17
Loop condition is false. Execution continues on line 532
508 uint32_t event_offset;
509 // Each offset entry is a uint32_t offset followed by a uint8_t maybe-flags
510 if (!wtap_read_bytes_or_eof(wth->fh, &event_offset, sizeof(event_offset), err, err_info))
12
Assuming the condition is false
13
Taking false branch
511 {
512 file_info_cleanup(file_info);
513 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 513, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
514 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
515 {
516 // Short read or EOF.
517 *err = 0;
518 g_free(*err_info);
519 *err_info = NULL((void*)0);
520 }
521 return WTAP_OPEN_NOT_MINE;
522 }
523 if (file_seek(wth->fh, 1, SEEK_CUR1, err) == -1)
14
Assuming the condition is false
15
Taking false branch
524 {
525 file_info_cleanup(file_info);
526 ws_debug("Failed to skip flags")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 526, __func__, "Failed to skip flags"); } } while (0)
;
527 return WTAP_OPEN_NOT_MINE;
528 }
529 file_info->event_offsets[idx] = GUINT32_FROM_LE(event_offset)(((guint32) (event_offset)));
530 }
531
532 if (file_seek(wth->fh, header->string_array_offset, SEEK_SET0, err) == -1)
18
Assuming the condition is false
19
Taking false branch
533 {
534 ws_debug("Failed to locate procmon string data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 534, __func__, "Failed to locate procmon string data"); } }
while (0)
;
535 return WTAP_OPEN_NOT_MINE;
536 }
537
538 uint32_t num_strings;
539 if (!wtap_read_bytes_or_eof(wth->fh, &num_strings, sizeof(num_strings), err, err_info))
20
Assuming the condition is false
21
Taking false branch
540 {
541 file_info_cleanup(file_info);
542 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 542, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
543 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
544 {
545 // Short read or EOF.
546 *err = 0;
547 g_free(*err_info);
548 *err_info = NULL((void*)0);
549 }
550 return WTAP_OPEN_NOT_MINE;
551 }
552 num_strings = GUINT32_FROM_LE(num_strings)(((guint32) (num_strings)));
553 if (num_strings > MAX_PROCMON_STRINGS(1000 * 1000)) {
22
Assuming the condition is false
23
Taking false branch
554 ws_debug("Truncating strings from %u to %u", num_strings, MAX_PROCMON_STRINGS)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 554, __func__, "Truncating strings from %u to %u", num_strings
, (1000 * 1000)); } } while (0)
;
555 num_strings = MAX_PROCMON_STRINGS(1000 * 1000);
556 }
557
558 // Strings aren't necessarily contiguous (or even in order?)
559 uint32_t *str_offsets = g_new(uint32_t, num_strings)((uint32_t *) g_malloc_n ((num_strings), sizeof (uint32_t)));
560 if (!wtap_read_bytes_or_eof(wth->fh, str_offsets, sizeof(uint32_t) * num_strings, err, err_info))
24
Assuming the condition is false
25
Taking false branch
561 {
562 file_info_cleanup(file_info);
563 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 563, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
564 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
565 {
566 // Short read or EOF.
567 *err = 0;
568 g_free(*err_info);
569 *err_info = NULL((void*)0);
570 }
571 g_free(str_offsets);
572 return WTAP_OPEN_NOT_MINE;
573 }
574#if G_BYTE_ORDER1234 == G_BIG_ENDIAN4321
575 for (unsigned idx = 0; idx < num_strings; idx++)
576 {
577 str_offsets[idx] = GUINT32_SWAP_LE_BE(str_offsets[idx])(((guint32) ( (((guint32) (str_offsets[idx]) & (guint32) 0x000000ffU
) << 24) | (((guint32) (str_offsets[idx]) & (guint32
) 0x0000ff00U) << 8) | (((guint32) (str_offsets[idx]) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (str_offsets
[idx]) & (guint32) 0xff000000U) >> 24))))
;
578 }
579#endif
580
581 file_info->string_array_size = num_strings;
582 file_info->string_array = g_new0(const char *, num_strings)((const char * *) g_malloc0_n ((num_strings), sizeof (const char
*)))
;
583 gunichar2 *str_buf = g_new(gunichar2, MAX_PROCMON_STRING_LENGTH)((gunichar2 *) g_malloc_n ((8192), sizeof (gunichar2)));
584 for (unsigned idx = 0; idx
25.1
'idx' is < 'num_strings'
< num_strings
; idx++) {
26
Loop condition is true. Entering loop body
31
Assuming 'idx' is >= 'num_strings'
32
Loop condition is false. Execution continues on line 605
585 if (file_seek(wth->fh, header->string_array_offset + str_offsets[idx], SEEK_SET0, err) == -1)
27
Assuming the condition is false
28
Taking false branch
586 {
587 file_info_cleanup(file_info);
588 g_free(str_offsets);
589 g_free(str_buf);
590 ws_debug("Failed to locate procmon string %u", idx)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 590, __func__, "Failed to locate procmon string %u", idx); }
} while (0)
;
591 return WTAP_OPEN_NOT_MINE;
592 }
593
594 const char *cur_str = procmon_read_string(wth->fh, str_buf, err, err_info);
595 if (!cur_str) {
29
Assuming 'cur_str' is non-null
30
Taking false branch
596 file_info_cleanup(file_info);
597 g_free(str_offsets);
598 g_free(str_buf);
599 ws_debug("Failed to read procmon string %u", idx)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 599, __func__, "Failed to read procmon string %u", idx); } }
while (0)
;
600 return WTAP_OPEN_NOT_MINE;
601 }
602
603 file_info->string_array[idx] = cur_str;
604 }
605 g_free(str_offsets);
606 g_free(str_buf);
607
608 if (file_seek(wth->fh, header->process_array_offset, SEEK_SET0, err) == -1)
33
Assuming the condition is false
34
Taking false branch
609 {
610 ws_debug("Failed to locate procmon process data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 610, __func__, "Failed to locate procmon process data"); } }
while (0)
;
611 return WTAP_OPEN_NOT_MINE;
612 }
613
614 uint32_t num_processes;
615 if (!wtap_read_bytes_or_eof(wth->fh, &num_processes, sizeof(num_processes), err, err_info))
35
Assuming the condition is false
36
Taking false branch
616 {
617 file_info_cleanup(file_info);
618 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 618, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
619 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
620 {
621 // Short read or EOF.
622 *err = 0;
623 g_free(*err_info);
624 *err_info = NULL((void*)0);
625 }
626 return WTAP_OPEN_NOT_MINE;
627 }
628 num_processes = GUINT32_FROM_LE(num_processes)(((guint32) (num_processes)));
629 if (num_processes > MAX_PROCMON_PROCESSES(500 * 1000)) {
37
Assuming the condition is false
38
Taking false branch
630 ws_debug("Truncating processes from %u to %u", num_processes, MAX_PROCMON_PROCESSES)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 630, __func__, "Truncating processes from %u to %u", num_processes
, (500 * 1000)); } } while (0)
;
631 num_processes = MAX_PROCMON_PROCESSES(500 * 1000);
632 }
633
634 uint32_t *process_indices = g_new(uint32_t, num_processes)((uint32_t *) g_malloc_n ((num_processes), sizeof (uint32_t))
)
;
635 if (!wtap_read_bytes_or_eof(wth->fh, process_indices, sizeof(uint32_t) * num_processes, err, err_info))
39
Assuming the condition is false
40
Taking false branch
636 {
637 file_info_cleanup(file_info);
638 g_free(process_indices);
639 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 639, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
640 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
641 {
642 // Short read or EOF.
643 *err = 0;
644 g_free(*err_info);
645 *err_info = NULL((void*)0);
646 }
647 return WTAP_OPEN_NOT_MINE;
648 }
649
650 uint32_t max_process_index = 0;
651 for (unsigned idx = 0; idx
40.1
'idx' is < 'num_processes'
< num_processes
; idx++) {
41
Loop condition is true. Entering loop body
44
Assuming 'idx' is >= 'num_processes'
45
Loop condition is false. Execution continues on line 655
652 process_indices[idx] = GUINT32_FROM_LE(process_indices[idx])(((guint32) (process_indices[idx])));
653 max_process_index = MAX(max_process_index, process_indices[idx])(((max_process_index) > (process_indices[idx])) ? (max_process_index
) : (process_indices[idx]))
;
42
Assuming the condition is false
43
'?' condition is false
654 }
655 g_free(process_indices);
656 if (max_process_index > MAX_PROCMON_PROCESSES(500 * 1000) * 2) {
46
Assuming the condition is false
47
Taking false branch
657 ws_debug("Truncating max process index from %u to %u", max_process_index, MAX_PROCMON_PROCESSES * 2)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 657, __func__, "Truncating max process index from %u to %u"
, max_process_index, (500 * 1000) * 2); } } while (0)
;
658 max_process_index = MAX_PROCMON_PROCESSES(500 * 1000) * 2;
659 }
660 file_info->process_index_map = g_new(uint32_t, max_process_index + 1)((uint32_t *) g_malloc_n ((max_process_index + 1), sizeof (uint32_t
)))
;
661 // Try to make invalid entries obvious.
662 memset(file_info->process_index_map, 0xff, sizeof(uint32_t) * (max_process_index + 1));
663 file_info->process_index_map_size = max_process_index + 1;
664
665 uint32_t *proc_offsets = g_new(uint32_t, num_processes)((uint32_t *) g_malloc_n ((num_processes), sizeof (uint32_t))
)
;
666 if (!wtap_read_bytes_or_eof(wth->fh, proc_offsets, sizeof(uint32_t) * num_processes, err, err_info))
48
Assuming the condition is false
49
Taking false branch
667 {
668 file_info_cleanup(file_info);
669 g_free(proc_offsets);
670 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 670, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
671 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
672 {
673 // Short read or EOF.
674 *err = 0;
675 g_free(*err_info);
676 *err_info = NULL((void*)0);
677 }
678 return WTAP_OPEN_NOT_MINE;
679 }
680
681 file_info->process_array = g_new(procmon_process_t, num_processes)((procmon_process_t *) g_malloc_n ((num_processes), sizeof (procmon_process_t
)))
;
50
Memory is allocated
682 file_info->process_array_size = num_processes;
683 for (unsigned idx = 0; idx < num_processes; idx++) {
51
Loop condition is true. Entering loop body
684 if (file_seek(wth->fh, header->process_array_offset + proc_offsets[idx], SEEK_SET0, err) == -1)
52
Assuming the condition is false
53
Taking false branch
685 {
686 file_info_cleanup(file_info);
687 g_free(proc_offsets);
688 ws_debug("Failed to locate procmon process %u", idx)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 688, __func__, "Failed to locate procmon process %u", idx);
} } while (0)
;
689 return WTAP_OPEN_NOT_MINE;
690 }
691 procmon_raw_process_t cur_raw_process;
692 if (!wtap_read_bytes_or_eof(wth->fh, &cur_raw_process, sizeof(cur_raw_process), err, err_info))
54
Assuming the condition is false
55
Taking false branch
693 {
694 file_info_cleanup(file_info);
695 g_free(proc_offsets);
696 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 696, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
697 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
698 {
699 // Short read or EOF.
700 *err = 0;
701 g_free(*err_info);
702 *err_info = NULL((void*)0);
703 }
704 return WTAP_OPEN_NOT_MINE;
705 }
706 uint32_t process_index = GUINT32_FROM_LE(cur_raw_process.process_index)(((guint32) (cur_raw_process.process_index)));
707 if (process_index <= max_process_index) {
56
Assuming 'process_index' is > 'max_process_index'
57
Taking false branch
708 file_info->process_index_map[process_index] = idx;
709 } else {
710 ws_debug("Process %u index %u exceeds max process index %u", idx, process_index, max_process_index)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 710, __func__, "Process %u index %u exceeds max process index %u"
, idx, process_index, max_process_index); } } while (0)
;
58
Taking true branch
59
Loop condition is false. Exiting loop
711 }
712 procmon_process_t *cur_process = &file_info->process_array[idx];
713 cur_raw_process.start_time = GUINT64_FROM_LE(cur_raw_process.start_time)(((guint64) (cur_raw_process.start_time)));
714 cur_raw_process.end_time = GUINT64_FROM_LE(cur_raw_process.end_time)(((guint64) (cur_raw_process.end_time)));
715 uint64_t filetime = GUINT64_FROM_LE(cur_raw_process.start_time)(((guint64) (cur_raw_process.start_time)));
716 filetime_to_nstime(&cur_process->start_time, filetime);
717 filetime = GUINT64_FROM_LE(cur_raw_process.end_time)(((guint64) (cur_raw_process.end_time)));
718 filetime_to_nstime(&cur_process->end_time, filetime);
719
720 cur_process->process_id = GUINT32_FROM_LE(cur_raw_process.process_id)(((guint32) (cur_raw_process.process_id)));
721 cur_process->parent_process_id = GUINT32_FROM_LE(cur_raw_process.parent_process_id)(((guint32) (cur_raw_process.parent_process_id)));
722 cur_process->parent_process_index = MAX(GUINT32_FROM_LE(cur_raw_process.parent_process_index), max_process_index)((((((guint32) (cur_raw_process.parent_process_index)))) >
(max_process_index)) ? ((((guint32) (cur_raw_process.parent_process_index
)))) : (max_process_index))
;
60
Assuming 'max_process_index' is >= field 'parent_process_index'
61
'?' condition is false
723 cur_process->authentication_id = GUINT64_FROM_LE(cur_raw_process.authentication_id)(((guint64) (cur_raw_process.authentication_id)));
724 cur_process->session_number = GUINT32_FROM_LE(cur_raw_process.session_number)(((guint32) (cur_raw_process.session_number)));
725 cur_process->is_virtualized = cur_raw_process.is_virtualized != 0;
62
Assuming field 'is_virtualized' is equal to 0
726 cur_process->is_64_bit = cur_raw_process.is_64_bit != 0;
63
Assuming field 'is_64_bit' is equal to 0
727 cur_process->integrity = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.integrity_si)(((guint32) (cur_raw_process.integrity_si))));
728 cur_process->user_name = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.user_name_si)(((guint32) (cur_raw_process.user_name_si))));
729 cur_process->process_name = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.process_name_si)(((guint32) (cur_raw_process.process_name_si))));
730 cur_process->image_path = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.image_path_si)(((guint32) (cur_raw_process.image_path_si))));
731 cur_process->command_line = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.command_line_si)(((guint32) (cur_raw_process.command_line_si))));
732 cur_process->company = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.company_si)(((guint32) (cur_raw_process.company_si))));
733 cur_process->version = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.version_si)(((guint32) (cur_raw_process.version_si))));
734 cur_process->description = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.description_si)(((guint32) (cur_raw_process.description_si))));
735 if (file_seek(wth->fh, header->system_bitness ? 8 : 4, SEEK_CUR1, err) == -1)
64
Assuming field 'system_bitness' is 0
65
'?' condition is false
66
Assuming the condition is false
67
Taking false branch
736 {
737 file_info_cleanup(file_info);
738 g_free(proc_offsets);
739 ws_debug("Failed to locate number of modules %u", idx)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 739, __func__, "Failed to locate number of modules %u", idx
); } } while (0)
;
740 return WTAP_OPEN_NOT_MINE;
741 }
742 uint32_t num_modules;
743 if (!wtap_read_bytes_or_eof(wth->fh, &num_modules, sizeof(num_modules), err, err_info))
68
Assuming the condition is false
744 {
745 file_info_cleanup(file_info);
746 g_free(proc_offsets);
747 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 747, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
748 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
749 {
750 // Short read or EOF.
751 *err = 0;
752 g_free(*err_info);
753 *err_info = NULL((void*)0);
754 }
755 return WTAP_OPEN_NOT_MINE;
756 }
757
758 cur_process->num_modules = MIN(GUINT32_FROM_LE(num_modules), MAX_PROCMON_MODULES)((((((guint32) (num_modules)))) < (1000)) ? ((((guint32) (
num_modules)))) : (1000))
;
69
Taking false branch
70
Assuming 'num_modules' is >= 1000
71
'?' condition is false
759 if (cur_process->num_modules
71.1
Field 'num_modules' is > 0
> 0) {
72
Taking true branch
760 cur_process->modules = g_new(procmon_module_t, cur_process->num_modules)((procmon_module_t *) g_malloc_n ((cur_process->num_modules
), sizeof (procmon_module_t)))
;
761 for (unsigned mod_idx = 0; mod_idx < cur_process->num_modules; mod_idx++) {
73
Loop condition is true. Entering loop body
762 if (cur_process->is_64_bit
73.1
Field 'is_64_bit' is false
) {
74
Taking false branch
763 procmon_raw_module_64_t cur_raw_module;
764 if (!wtap_read_bytes_or_eof(wth->fh, &cur_raw_module, sizeof(cur_raw_module), err, err_info)) {
765 file_info_cleanup(file_info);
766 g_free(proc_offsets);
767 g_free(cur_process->modules);
768 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 768, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
769 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
770 {
771 // Short read or EOF.
772 *err = 0;
773 g_free(*err_info);
774 *err_info = NULL((void*)0);
775 }
776 return WTAP_OPEN_NOT_MINE;
777 }
778 procmon_module_t *cur_module = &cur_process->modules[mod_idx];
779 cur_module->base_address = GUINT64_FROM_LE(cur_raw_module.base_address)(((guint64) (cur_raw_module.base_address)));
780 cur_module->size = GUINT32_FROM_LE(cur_raw_module.size)(((guint32) (cur_raw_module.size)));
781 cur_module->image_path = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.image_path_si)(((guint32) (cur_raw_module.image_path_si))));
782 cur_module->version = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.version_si)(((guint32) (cur_raw_module.version_si))));
783 cur_module->company = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.company_si)(((guint32) (cur_raw_module.company_si))));
784 cur_module->description = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.description_si)(((guint32) (cur_raw_module.description_si))));
785 // filetime = GUINT64_FROM_LE(cur_raw_module.timestamp);
786 // filetime_to_nstime(&cur_module->timestamp, filetime);
787 } else {
788 procmon_raw_module_32_t cur_raw_module;
789 if (!wtap_read_bytes_or_eof(wth->fh, &cur_raw_module, sizeof(cur_raw_module), err, err_info)) {
75
Assuming the condition is true
76
Taking true branch
790 file_info_cleanup(file_info);
77
Calling 'file_info_cleanup'
82
Returning; memory was released
791 g_free(proc_offsets);
792 g_free(cur_process->modules);
83
Use of memory after it is freed
793 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 793, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
794 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12)
795 {
796 // Short read or EOF.
797 *err = 0;
798 g_free(*err_info);
799 *err_info = NULL((void*)0);
800 }
801 return WTAP_OPEN_NOT_MINE;
802 }
803 procmon_module_t *cur_module = &cur_process->modules[mod_idx];
804 cur_module->base_address = GUINT32_FROM_LE(cur_raw_module.base_address)(((guint32) (cur_raw_module.base_address)));
805 cur_module->size = GUINT32_FROM_LE(cur_raw_module.size)(((guint32) (cur_raw_module.size)));
806 cur_module->image_path = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.image_path_si)(((guint32) (cur_raw_module.image_path_si))));
807 cur_module->version = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.version_si)(((guint32) (cur_raw_module.version_si))));
808 cur_module->company = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.company_si)(((guint32) (cur_raw_module.company_si))));
809 cur_module->description = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.description_si)(((guint32) (cur_raw_module.description_si))));
810 // filetime = GUINT64_FROM_LE(cur_raw_module.timestamp);
811 // filetime_to_nstime(&cur_module->timestamp, filetime);
812 }
813 }
814 } else {
815 cur_process->modules = NULL((void*)0);
816 }
817 }
818 g_free(proc_offsets);
819
820 if (file_seek(wth->fh, header->start_events_offset, SEEK_SET0, err) == -1)
821 {
822 ws_debug("Failed to locate procmon events data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c"
, 822, __func__, "Failed to locate procmon events data"); } }
while (0)
;
823 return WTAP_OPEN_NOT_MINE;
824 }
825
826 wth->meta_events = g_array_new(false0, false0, sizeof(wtap_block_t));
827
828 wth->priv = file_info;
829 wth->file_type_subtype = procmon_file_type_subtype;
830 wth->file_encap = WTAP_ENCAP_PROCMON227;
831
832 wth->snapshot_length = 0;
833 wth->file_tsprec = WTAP_TSPREC_SEC0;
834
835 wth->subtype_read = procmon_read;
836 wth->subtype_seek_read = procmon_seek_read;
837
838 return WTAP_OPEN_MINE;
839}
840
841/* Options for meta event blocks. */
842static const struct supported_option_type ft_specific_event_block_options_supported[] = {
843 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
844 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
845 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
846 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
847 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED }
848};
849
850static const struct supported_block_type procmon_blocks_supported[] = {
851
852 /* Multiple file-type specific events (including local ones). */
853 { WTAP_BLOCK_FT_SPECIFIC_EVENT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(ft_specific_event_block_options_supported)(sizeof (ft_specific_event_block_options_supported) / sizeof (
ft_specific_event_block_options_supported)[0]), ft_specific_event_block_options_supported
},
854
855 /* Multiple custom blocks. */
856 { WTAP_BLOCK_CUSTOM, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED0, ((void*)0) },
857};
858
859static const struct file_type_subtype_info procmon_info = {
860 "MS Procmon files", "procmon", NULL((void*)0), NULL((void*)0),
861 false0, BLOCKS_SUPPORTED(procmon_blocks_supported)(sizeof (procmon_blocks_supported) / sizeof (procmon_blocks_supported
)[0]), procmon_blocks_supported
,
862 NULL((void*)0), NULL((void*)0), NULL((void*)0)
863};
864
865void register_procmon(void)
866{
867 procmon_file_type_subtype = wtap_register_file_type_subtype(&procmon_info);
868
869 /*
870 * Register name for backwards compatibility with the
871 * wtap_filetypes table in Lua.
872 */
873 wtap_register_backwards_compatibility_lua_name("Procmon", procmon_file_type_subtype);
874}
875
876/*
877 * Editor modelines - https://www.wireshark.org/tools/modelines.html
878 *
879 * Local Variables:
880 * c-basic-offset: 4
881 * tab-width: 8
882 * indent-tabs-mode: nil
883 * End:
884 *
885 * vi: set shiftwidth=4 tabstop=8 expandtab:
886 * :indentSize=4:tabSize=8:noTabs=true:
887 */