-
Notifications
You must be signed in to change notification settings - Fork 110
/
Copy pathappverifier_xml.py
266 lines (240 loc) · 16.6 KB
/
appverifier_xml.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0.
# Built-in
import xml.etree.ElementTree as ElementTree
import argparse
s_AppVerifier_LogText = "{Application Verifier}logSession"
s_AppVerifier_EntryText = "{Application Verifier}logEntry"
s_AppVerifier_ErrorSeverities = ["Warning", "Error", "UNKNOWN"]
# A dictionary to take the error codes and convert them to basic information
# on what went wrong.
#
# How to adjust/learn more:
# To add/remove from this list, run "appverif" in a Windows terminal with
# administrator privileges and then press F1 to get the help page. Then search
# for the error code you got (minus the "0x" part at the beginning) and use the
# information there to add/adjust the entry in the dictionary below.
s_AppVerifier_ErrorCodeHelp = {
"Exceptions": {
"0x650": "The application is trying to run code from an address that is non-executable or free"
},
"Handles": {
"0x300": "The function on the top of the stack passed an invalid handle to system routines",
"0x301": "The function on the top of the stack passed an invalid TLS index to TLS system routines",
"0x302": "The function on the top of the stack called WaitForMultipleObjects with NULL as the address "
"of the array of handles to wait for or with zero as the number of handles",
"0x303": "The function on the top of the stack passed a NULL handle to system routines",
"0x304": "The current thread is currently running code inside the DllMain function of one "
"of the DLLs loaded in the current process and it calls WaitForSingleObject or "
"WaitForMultipleObjects to wait on a thread handle in the same process",
"0x305": "The current thread is calling an API with a handle to an object with an incorrect object type"
},
"Heaps": {
"0x01": "Unknown error encountered that cannot be determined/classified by AppVerifier",
"0x02": "The application touched non-accessible page. Typically is caused by a buffer overrun error",
"0x03": "A heap created with HEAP_NO_SERIALIZE flag was accessed simultaneously from two threads",
"0x04": "The size of the block in a 'HeapAlloc' or 'HeapReAlloc' operation was above any reasonable value",
"0x05": "Heap structure did not include magic value from AppVerifier - meaning somehow the internal heap "
"structure was corrupted or a bogus value was used as heap handle",
"0x06": "Typically means block was allocated in one heap and freed in another",
"0x07": "Block was freed twice",
"0x08": "Generic error due to corruption in the heap block that AppVerifier cannot place more specifically",
"0x09": "Tried to destroy the default process heap",
"0x0A": "Access violation raised while executing heap manager code",
"0x0B": "AppVerifier could not determine any particular type of corruption for the block. "
"Generally means heap points to non-accessible memory area",
"0x0C": "AppVerifier could not determine any particular type of corruption for the block. "
"Generally happens if during heap free operation you pass an address that poins to a non-accessible memory area. "
"Can also occur with double free situations",
"0x0D": "Block of memory is written to after being freed",
"0x0E": "Freed block marked as non-accessible had access attempt",
"0x0F": "Magic pattern added by AppVerifier at end of heap block changed. "
"Typically means buffer overrun errors",
"0x10": "Buffer underruns",
"0x11": "Buffer underruns",
"0x12": "Buffer underruns",
"0x13": "Non-accessible page at end of heap allocation was touched. Typically caused by a buffer overrun error",
"0x14": "Page heap manager detected internal inconsistencies while calling GetProcessHeaps"
},
"Leak": {
"0x900": "Owner DLL of the allocation was dynamically unloaded while owning resources",
"0x901": "Owner DLL of the handle was dynamically unloaded while owning resources",
"0x902": "Owner DLL of the registry key was dynamically unloaded while owning resources",
"0x903": "Owner DLL of the virtual reservation was dynamically unloaded while owning resources",
"0x904": "Owner DLL of the SysString was dynamically unloaded while owning resources",
"0x905": "DLL registered for power notification was dynamically unloaded without registering",
"0x906": "Owner DLL of the COM allocation was dynamically unloaded while owning resources"
},
"Locks": {
"0x200": "A thread is terminated, suspended, or in a state in which it cannot hold a critical section",
"0x201": "A DLL has a global variable containing a critical section and the DLL is unloaded but the "
"critical section has not been deleted",
"0x202": "A heap allocation contains a critical section, the allocation is freed, and the critical section "
"has not been deleted",
"0x203": "Typicaly means a critical section has been initialized more than once. May mean the critical section "
"or its debug information structure has been corrupted",
"0x204": "Memory containing a critical section was freed but the critical section has not been deleted using 'DeleteCriticalSection'",
"0x205": "The DebugInfo field of the critical section is pointing to freed memory",
"0x206": "The owner thread ID is invalid in the current context",
"0x207": "The recursion count field of the critical section structure is invalid in the current context",
"0x208": "A critical section is owned by a thread if it is deleted or if the critical section is uninitialized",
"0x209": "A critical section is released more times than the current thread acquired it",
"0x210": "A critical section is used without being initialized or after it has been deleted",
"0x211": "A critical section is reinitialized by the current thread",
"0x212": "The current thread is calling VirtualFree on a memory block that contains an active critical section",
"0x213": "The current thread is calling UnmapViewOfFile on a memory block that contains an active critical section",
"0x214": "The current thread calling LeaveCriticalSection but does not own any critical section",
"0x215": "The current thread tries to use a private lock that lives inside another DLL"
},
"Memory": {
"0x600": "AppVerifier detects a VirtualFree or a DLL unload with an invalid start adress or size of the memory allocation",
"0x601": "AppVerifier detects a VirtualAlloc call with an invalid start adress or size of the memory allocation",
"0x602": "AppVerifier detects a MapViewOfFile call with an invalid base address or size of the mapping",
"0x603": "AppVerifier detects an IsBadXXXPtr call with an invalid address for the memory buffer to be probed",
"0x604": "AppVerifier detects an IsBadXXXPtr call for a memory allocation that is free",
"0x605": "AppVerifier detects an IsBadXXXPtr call for a memory allocation that contains at least one GUARD_PAGE",
"0x606": "AppVerifier detects an IsBadXXXPtr call with a NULL address",
"0x607": "AppVerifier detects an IsBadXXXPtr call with an invalid start address or invalid size for the memory buffer to be probed",
"0x608": "AppVerifier detects a DLL unload with an invalid start address for the size of the DLL memory range",
"0x609": "AppVerifier detects a VirtualFree for a block of memory that is actually part of the current thread's stack",
"0x60A": "AppVerifier detects a VirtualFree with an incorrect value for the FreeType parameter",
"0x60B": "AppVerifier detects a VirtualFree for an address that is already free",
"0x60C": "AppVerifier detects a VirtualFree with a non-zero value for the dwSize parameter",
"0x60D": "A DLL's entry point function is raising an exception",
"0x60E": "A thread function is raising an exception",
"0x60F": "An exception occured during an IsBadXXXPtr call",
"0x610": "AppVerifier detects a VirtualFree call with a NULL first parameter",
"0x612": "AppVerifier detects a HeapFree for a block of memory that is actually part of the current thread's stack",
"0x613": "AppVerifier detects an UnmapViewOfFile for a block of memory that is actually part of the current thread's stack",
"0x614": "The application is trying to use NULL or some other incorrect address as the address of a valid object",
"0x615": "The application is trying to use NULL or some other incorrect address as the address of a valid object",
"0x616": "The application is trying to run code from an address that is non-executable or free",
"0x617": "An exception occurred while initializing a buffer specified as output parameter for a Win32 or (non-AWS) CRT API",
"0x618": "An exception occurred while calling HeapSize for a heap block that is being freed",
"0x619": "The program is calling VirtualFree with an IpAddress parameter that is not the base address returned by "
"the VirtualAlloc or VirtualAllocEx function when the region of pages was reserved",
"0x61A": "The program is calling UnmapViewOfFile with an IpBaseAddress parameter that is not identical to the value returned"
"by a previous call to the MapViewOfFile or MapViewOfFileEx function",
"0x61B": "A callback function in the threadpool thread is rasing an exception",
"0x61C": "The application is trying to run code from an address that is non-executable or free",
"0x61D": "The application is created an executable heap",
"0x61E": "The application is allocating executable memory"
},
"SRWLock": {
"0x250": "A thread tried to use SRW lock that is not initalized",
"0x251": "The SRW lock is being re-initialized",
"0x252": "The SRW lock is being released with a wrong release API",
"0x253": "The SRW lock is being acquired recursively by the same thread",
"0x254": "The thread that owns the SRW lock is exiting or being terminated",
"0x255": "The SRW lock is being released by the thread that did not acquire the lock",
"0x256": "The memory address being freed contains an active SRW lock that is still in use",
"0x257": "The DLL being unloaded contains an active SRW lock that is still in use"
},
"Threadpool": {
"0x700": "Thread priority is changed when thread is returned to threadpool",
"0x701": "Thread affinity is changed when thread is returned to threadpool",
"0x702": "One or more messages left as unprocessed when threadpool thread is returned to the threadpool",
"0x703": "Any window is kept alive when threadpool thread is returned to the threadpool",
"0x704": "ExitThread is called on a threadpool thread",
"0x705": "Callback function changed the thread token to impersonate another user and forgot to reset it before "
"returning it to the threadpool",
"0x706": "Windows API that requires dedicated or persistent thread called from threadpool",
"0x707": "Callback function forgot to close or reset the current transaction handle",
"0x708": "Callback function called CoInit and CoUnInit in differing amounts (unbalanced)",
"0x709": "The period to signal the timer is not zero when the timer is set to signal only once with the WT_EXECUTEONLYONCE flag",
"0x70A": "The loader lock is held within the callback and is not released when the thread is returned to the threadpool",
"0x70B": "The preferred language is set within the callback and is not cleared when the thread is returned to the threadpool",
"0x70C": "The background priority is set within the callback and is not disabled when the thread is returned to the threadpool",
"0x70D": "TerminateThread called on a threadpool thread",
},
"TLS": {
"0x350": "A DLL that allocated a TLS index is being unloaded before freeing that TLS index",
"0x351": "The internal verifier structures used to store the state of TLS slots for thread are corrupted",
"0x352": "An invalid TLS index is used"
}
}
def parseXML(filepath, dump_xml_on_error):
xml_is_app_verifier = False
app_verifier_entries = []
print("Looking for AppVerifier XML file...")
xml_tree = ElementTree.parse(filepath)
# Go through every element in the XML tree
for elem in xml_tree.iter():
if (elem.tag == s_AppVerifier_LogText):
xml_is_app_verifier = True
elif (elem.tag == s_AppVerifier_EntryText):
app_verifier_entries.append(elem)
# If the XML does not have any AppVerifier data, then something went wrong!
if (xml_is_app_verifier == False):
print("ERROR: XML File from AppVerifier does not include a AppVerifier session!")
return -1
# If we have AppVerifier entries, then a test or tests failed, so process the data,
# print it, and then return with an error to stop the GitHub action from passing
if (len(app_verifier_entries) > 0):
print("WARNING: AppVerifier entries found:")
severity_error_found = False
for entry in app_verifier_entries:
element_time = entry.attrib.get("Time", "UNKNOWN")
element_layer_name = entry.attrib.get("LayerName", "UNKNOWN")
element_code = entry.attrib.get("StopCode", "UNKNOWN")
element_severity = entry.attrib.get("Severity", "UNKNOWN")
print_red = False
if (element_severity in s_AppVerifier_ErrorSeverities):
severity_error_found = True
print_red = True
if (print_red):
print(
f"ERROR: [{element_time}] {element_severity.upper()} - Test: {element_layer_name} - Stop Code: {element_code}")
else:
print(
f"[{element_time}] {element_severity.upper()} - Test: {element_layer_name} - Stop Code: {element_code}")
print(f"\t{getErrorCodeMeaning(element_layer_name, element_code)}")
print(
"\nNOTE: The error codes and information provided are just guesses based on the error code.\n"
"\tRun AppVerifier locally and use WinDBG combined with the AppVerifier help to discover more "
"about the error from its error code and how to debug it.")
if (severity_error_found == True and dump_xml_on_error != None):
if (dump_xml_on_error == True):
print("\nERROR: Raw XML output for errors found:\n")
for entry in app_verifier_entries:
print(ElementTree.tostring(
entry, encoding="unicode"))
if (severity_error_found == True):
print(
"\nERROR: Failed due to AppVerifier finding entries marked as severe")
return -1
else:
print("SUCCESS: AppVerifier entries were not marked as severe")
return 0
else:
print("SUCCESS: No AppVerifier entries found! AppVerifier ran successfully and did not generate any entries")
return 0
def getErrorCodeMeaning(element_layer_name, element_code):
if (element_layer_name in s_AppVerifier_ErrorCodeHelp):
layer_codes = s_AppVerifier_ErrorCodeHelp[element_layer_name]
if (element_code in layer_codes):
return layer_codes[element_code]
else:
return "Util-script unknown error: " + element_code + " for layer " + element_layer_name
return "Util-script unknown layer: " + element_layer_name + " and error code: " + element_code
def booleanString(string):
string = string.lower()
if string not in {"false", "true"}:
raise ValueError("Boolean is not true or false!")
return string == "true"
def main():
argument_parser = argparse.ArgumentParser(
description="AppVerifier XML output util")
argument_parser.add_argument("--xml_file", metavar="<C:\\example\\file.xml>",
required=False, help="Path to XML file from AppVerifier")
argument_parser.add_argument("--dump_xml_on_error", metavar="<True/False>", default=True, required=False,
type=booleanString, help="If true, the XML for found issues will be printed to the console")
parsed_commands = argument_parser.parse_args()
print("\nStarting AppVerifier XML check...", flush=True)
print(parsed_commands.dump_xml_on_error)
xml_result = parseXML(parsed_commands.xml_file,
parsed_commands.dump_xml_on_error)
print("\n")
exit(xml_result)
if __name__ == "__main__":
main()