forked from google/vanir
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser_test.py
150 lines (136 loc) · 5.77 KB
/
parser_test.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
# Copyright 2023 Google LLC
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
"""Tests for parser."""
from vanir import parser
from absl.testing import absltest
from pybind11_abseil import status
class ParserTest(absltest.TestCase):
def test_parser(self):
testcode = """
/* This code is for testing Vanir Parser. */ int test_globalvar = 10;
int test_func1(const unsigned int64 test_arg) {
const struct teststruct *testvar = (struct teststruct *)globalvar->data;
test_func2(test_arg, testvar); // some comment.
/* additional comment line. */
0xe8(); // broken code -- won't be counted as func call.
return 0;
}
int test_func_decl(int myarg);
"""
testfile = self.create_tempfile('testfile.c', content=testcode)
filename = testfile.full_path
test_target_file = 'foo/bar/testfile.c'
test_parser = parser.Parser(filename, test_target_file)
function_chunks = test_parser.get_function_chunks()
line_chunk = test_parser.get_line_chunk()
self.assertLen(function_chunks, 1)
self.assertEqual(function_chunks[0].base.name, 'test_func1')
self.assertEqual(function_chunks[0].base.parameters, ['test_arg'])
self.assertCountEqual(
function_chunks[0].base.used_data_types,
[['const', 'unsigned', 'int64'], ['const', 'struct', 'teststruct'],
['struct', 'teststruct']])
self.assertEqual(function_chunks[0].base.local_variables, ['testvar'])
self.assertEqual(function_chunks[0].base.called_functions, ['test_func2'])
self.assertEqual(function_chunks[0].target_file, test_target_file)
self.assertIsNotNone(function_chunks[0].normalized_code)
self.assertIsNotNone(function_chunks[0].function_hash)
expected_tokens = {
2: ['int', 'test_globalvar', '=', '10', ';'],
3: [
'int', 'test_func1', '(', 'const', 'unsigned', 'int64', 'test_arg',
')', '{'
],
4: [
'const', 'struct', 'teststruct', '*', 'testvar', '=', '(', 'struct',
'teststruct', '*', ')', 'globalvar', '->', 'data', ';'
],
5: ['test_func2', '(', 'test_arg', ',', 'testvar', ')', ';'],
7: ['0xe8', '(', ')', ';'],
8: ['return', '0', ';'],
9: ['}'],
10: ['int', 'test_func_decl', '(', 'int', 'myarg', ')', ';']
}
self.assertEqual(line_chunk.base.tokens, expected_tokens)
self.assertEqual(line_chunk.target_file, test_target_file)
self.assertIsNotNone(line_chunk.normalized_code)
self.assertIsNotNone(line_chunk.line_hashes)
self.assertIsNotNone(line_chunk.used_lines)
def test_parser_with_affected_ranges(self):
testcode = r"""
int unaffected_function1(void) { printk("ok"); }
void affected_function1(void) {
printk("this line is vulnerable. %s", sensitive_info);
}
int unaffected_function2(void) { printk("this is fine."); }
void affected_function2(void) {
printk("this line is also vulnerable. %s", sensitive_info);
}
int unaffected_function3(void) { printk("this is fine, too."); }
void affected_function3(void) {
printk("this line is also vulnerable. %s", sensitive_info);
}
int unaffected_function4(void) { printk("this is fine, too."); }
"""
affected_ranges = [(4, 4), (7, 7), (13, 13)]
testfile = self.create_tempfile('testfile.c', content=testcode)
filename = testfile.full_path
test_target_file = 'foo/bar/testfile.c'
test_parser = parser.Parser(filename, test_target_file, affected_ranges)
function_chunks = test_parser.get_function_chunks()
line_chunk = test_parser.get_line_chunk()
self.assertLen(function_chunks, 3)
self.assertEqual(function_chunks[0].base.name, 'affected_function1')
self.assertEqual(function_chunks[1].base.name, 'affected_function2')
self.assertEqual(function_chunks[2].base.name, 'affected_function3')
expected_tokens = {
2: [
'int', 'unaffected_function1', '(', 'void', ')', '{', 'printk', '(',
'"ok"', ')', ';', '}'
],
3: ['void', 'affected_function1', '(', 'void', ')', '{'],
4: [
'printk', '(', '"this line is vulnerable. %s"', ',',
'sensitive_info', ')', ';'
],
5: ['}'],
6: [
'int', 'unaffected_function2', '(', 'void', ')', '{', 'printk', '(',
'"this is fine."', ')', ';', '}'
],
7: ['void', 'affected_function2', '(', 'void', ')', '{'],
8: [
'printk', '(', '"this line is also vulnerable. %s"', ',',
'sensitive_info', ')', ';'
],
9: ['}'],
10: [
'int', 'unaffected_function3', '(', 'void', ')', '{', 'printk', '(',
'"this is fine, too."', ')', ';', '}'
],
11: ['void', 'affected_function3', '(', 'void', ')', '{'],
12: [
'printk', '(', '"this line is also vulnerable. %s"', ',',
'sensitive_info', ')', ';'
],
13: ['}'],
14: [
'int', 'unaffected_function4', '(', 'void', ')', '{', 'printk', '(',
'"this is fine, too."', ')', ';', '}'
]
}
self.assertEqual(line_chunk.base.tokens, expected_tokens)
self.assertEqual(line_chunk.target_file, test_target_file)
self.assertIsNotNone(line_chunk.normalized_code)
self.assertIsNotNone(line_chunk.line_hashes)
self.assertIsNotNone(line_chunk.used_lines)
def test_parser_with_init_failure(self):
filename = 'NonExistingFile.c'
test_target_file = 'foo/bar/testfile.c'
with self.assertRaisesRegex(status.StatusNotOk, 'Failed to open file:.*'):
parser.Parser(filename, test_target_file)
if __name__ == '__main__':
absltest.main()