### Bug Summary

File: | wiretap/procmon.c
Warning: | line 712, column 32 Use of memory after it is freed

### Annotated Source Code

Press '?' to see keyboard shortcuts

Show analyzer invocation
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/2025-12-10-100316-3573-1 -x c /builds/wireshark/wireshark/wiretap/procmon.c

Keyboard shortcuts:

- Use 'j/k' keys for keyboard navigation
- Use 'Shift+S' to show/hide relevant lines
- Use '?' to toggle this window

Close
Show only relevant lines Show control flow arrows

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