Skip to content

Commit

Permalink
[test] Add unit tests for sanitizer output converters
Browse files Browse the repository at this point in the history
Add new unit tests for `asan`, `msan`, `tsan` and `ubsan` sanitizers.
  • Loading branch information
csordasmarton committed Jan 15, 2020
1 parent 3bdc93b commit 6d1a928
Show file tree
Hide file tree
Showing 25 changed files with 1,203 additions and 0 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ script:
make clean_travis &&
make package &&
make -C tools/plist_to_html test &&
make -C tools/warning-to-plist test &&
if [[ "$CC_MODULE" = "analyzer" ]]; then
BUILD_DIR=$TRAVIS_BUILD_DIR/build make -C analyzer \
test_unit \
Expand Down
52 changes: 52 additions & 0 deletions tools/warning-to-plist/tests/unit/asan_output_test_files/asan.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
=================================================================
==12457==ERROR: AddressSanitizer: heap-use-after-free on address 0x614000000044 at pc 0x0000004f4b45 bp 0x7ffd40559120 sp 0x7ffd40559118
READ of size 4 at 0x614000000044 thread T0
#0 0x4f4b44 in main files/asan.cpp:5:10
#1 0x7f334b52eb96 in __libc_start_main (??)
#2 0x41aaf9 in _start (??)

0x614000000044 is located 4 bytes inside of 400-byte region [0x614000000040,0x6140000001d0)
freed by thread T0 here:
#0 0x4f2962 in operator delete[](void*) asan_new_delete.cc:170:3
#1 0x4f4af6 in main files/asan.cpp:4:3
#2 0x7f334b52eb96 in __libc_start_main (??)

previously allocated by thread T0 here:
#0 0x4f1d32 in operator new[](unsigned long) asan_new_delete.cc:109:3
#1 0x4f4ad4 in main files/asan.cpp:3:16
#2 0x7f334b52eb96 in __libc_start_main (??)

SUMMARY: AddressSanitizer: heap-use-after-free files/asan.cpp:5:10 in main
Shadow bytes around the buggy address:
0x0c287fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c287fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c287fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c287fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c287fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c287fff8000: fa fa fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd
0x0c287fff8010: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c287fff8020: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c287fff8030: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
0x0c287fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c287fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==12457==ABORTING
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>diagnostics</key>
<array>
<dict>
<key>category</key>
<string>unknown</string>
<key>check_name</key>
<string>AddressSanitizer</string>
<key>description</key>
<string>heap-use-after-free on address 0x614000000044 at pc 0x0000004f4b45 bp 0x7ffd40559120 sp 0x7ffd40559118</string>
<key>issue_hash_content_of_line_in_context</key>
<string>8cdbdf52c8542acf9393deee98235edb</string>
<key>location</key>
<dict>
<key>col</key>
<integer>10</integer>
<key>file</key>
<integer>0</integer>
<key>line</key>
<integer>5</integer>
</dict>
<key>notes</key>
<array>
<dict>
<key>depth</key>
<integer>0</integer>
<key>kind</key>
<string>note</string>
<key>location</key>
<dict>
<key>col</key>
<integer>10</integer>
<key>file</key>
<integer>0</integer>
<key>line</key>
<integer>5</integer>
</dict>
<key>message</key>
<string>READ of size 4 at 0x614000000044 thread T0
#0 0x4f4b44 in main files/asan.cpp:5:10
#1 0x7f334b52eb96 in __libc_start_main (??)
#2 0x41aaf9 in _start (??)
</string>
</dict>
</array>
<key>path</key>
<array>
<dict>
<key>depth</key>
<integer>0</integer>
<key>kind</key>
<string>event</string>
<key>location</key>
<dict>
<key>col</key>
<integer>10</integer>
<key>file</key>
<integer>0</integer>
<key>line</key>
<integer>5</integer>
</dict>
<key>message</key>
<string> #0 0x4f4b44 in main files/asan.cpp:5:10</string>
</dict>
<dict>
<key>depth</key>
<integer>0</integer>
<key>kind</key>
<string>event</string>
<key>location</key>
<dict>
<key>col</key>
<integer>10</integer>
<key>file</key>
<integer>0</integer>
<key>line</key>
<integer>5</integer>
</dict>
<key>message</key>
<string>heap-use-after-free on address 0x614000000044 at pc 0x0000004f4b45 bp 0x7ffd40559120 sp 0x7ffd40559118</string>
</dict>
</array>
<key>type</key>
<string>asan</string>
</dict>
</array>
<key>files</key>
<array>
<string>files/asan.cpp</string>
</array>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
int main(int argc, char **argv)
{
int *array = new int[100];
delete [] array;
return array[argc];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <stdio.h>

int main(int argc, char** argv)
{
int* a = new int[10];
a[5] = 0;
if (a[argc])
printf("xx\n");
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
==12680==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x4940da in main files/msan.cpp:7:7
#1 0x7fed9df58b96 in __libc_start_main (??)
#2 0x41b2d9 in _start (??)

SUMMARY: MemorySanitizer: use-of-uninitialized-value files/msan.cpp:7:7 in main
Exiting
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>diagnostics</key>
<array>
<dict>
<key>category</key>
<string>unknown</string>
<key>check_name</key>
<string>MemorySanitizer</string>
<key>description</key>
<string>use-of-uninitialized-value</string>
<key>issue_hash_content_of_line_in_context</key>
<string>bbcfe23432808e76f0c771aacb4c377a</string>
<key>location</key>
<dict>
<key>col</key>
<integer>7</integer>
<key>file</key>
<integer>0</integer>
<key>line</key>
<integer>7</integer>
</dict>
<key>notes</key>
<array>
<dict>
<key>depth</key>
<integer>0</integer>
<key>kind</key>
<string>note</string>
<key>location</key>
<dict>
<key>col</key>
<integer>7</integer>
<key>file</key>
<integer>0</integer>
<key>line</key>
<integer>7</integer>
</dict>
<key>message</key>
<string> #0 0x4940da in main files/msan.cpp:7:7
#1 0x7fed9df58b96 in __libc_start_main (??)
#2 0x41b2d9 in _start (??)
</string>
</dict>
</array>
<key>path</key>
<array>
<dict>
<key>depth</key>
<integer>0</integer>
<key>kind</key>
<string>event</string>
<key>location</key>
<dict>
<key>col</key>
<integer>7</integer>
<key>file</key>
<integer>0</integer>
<key>line</key>
<integer>7</integer>
</dict>
<key>message</key>
<string> #0 0x4940da in main files/msan.cpp:7:7</string>
</dict>
<dict>
<key>depth</key>
<integer>0</integer>
<key>kind</key>
<string>event</string>
<key>location</key>
<dict>
<key>col</key>
<integer>7</integer>
<key>file</key>
<integer>0</integer>
<key>line</key>
<integer>7</integer>
</dict>
<key>message</key>
<string>use-of-uninitialized-value</string>
</dict>
</array>
<key>type</key>
<string>msan</string>
</dict>
</array>
<key>files</key>
<array>
<string>files/msan.cpp</string>
</array>
</dict>
</plist>
114 changes: 114 additions & 0 deletions tools/warning-to-plist/tests/unit/test_asan_output_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# -----------------------------------------------------------------------------
# The CodeChecker Infrastructure
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
# -----------------------------------------------------------------------------

"""
This module tests the correctness of the OutputParser and PListConverter, which
used in sequence transform AddressSanitizer output to a plist file.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import os
import unittest

try:
from StringIO import StringIO
except ImportError:
from io import BytesIO as StringIO

from warning_to_plist.converter.output_parser import Event, Message
from warning_to_plist.converter.sanitizers.address.output_parser import \
ASANOutputParser
from warning_to_plist.converter.sanitizers.address.plist_converter import \
ASANPlistConverter

OLD_PWD = None


def setup_module():
"""Setup the test tidy reprs for the test classes in the module."""
global OLD_PWD
OLD_PWD = os.getcwd()
os.chdir(os.path.join(os.path.dirname(__file__),
'asan_output_test_files'))

asan_repr = [
Message(
os.path.abspath('files/asan.cpp'),
5, 10,
"heap-use-after-free on address 0x614000000044 at pc "
"0x0000004f4b45 bp 0x7ffd40559120 sp 0x7ffd40559118",
"AddressSanitizer",
[Event(
os.path.abspath('files/asan.cpp'),
5, 10,
" #0 0x4f4b44 in main files/asan.cpp:5:10"
)],
[Event(
os.path.abspath('files/asan.cpp'),
5, 10,
"READ of size 4 at 0x614000000044 thread T0\n"
" #0 0x4f4b44 in main files/asan.cpp:5:10\n"
" #1 0x7f334b52eb96 in __libc_start_main (??)\n"
" #2 0x41aaf9 in _start (??)\n"
)]
),
]

ASANOutputParserTestCase.asan_repr = asan_repr
ASANPListConverterTestCase.asan_repr = asan_repr


def teardown_module():
"""Restore environment after tests have ran."""
global OLD_PWD
os.chdir(OLD_PWD)


class ASANPListConverterTestCase(unittest.TestCase):
"""
Test the output of the PListConverter, which converts Messages to plist
format.
"""

def setUp(self):
"""Setup the PListConverter."""
self.plist_conv = ASANPlistConverter()

def test_asan(self):
"""Test for the asan.plist file."""
self.plist_conv.add_messages(self.asan_repr)

# use relative path for this test
self.plist_conv.plist['files'][0] = 'files/asan.cpp'

output = StringIO()
self.plist_conv.write(output)

with open('asan.plist') as pfile:
exp = pfile.read()
self.assertEqual(exp, output.getvalue())

output.close()


class ASANOutputParserTestCase(unittest.TestCase):
"""
Tests the output of the OutputParser, which converts an Address Sanitizer
output file to zero or more Message object.
"""

def setUp(self):
"""Setup the OutputParser."""
self.parser = ASANOutputParser()

def test_asan(self):
""" Test the generated Messages of msan.out. """
messages = self.parser.parse_messages_from_file('asan.out')
self.assertEqual(len(messages), len(self.asan_repr))
for message in messages:
self.assertIn(message, self.asan_repr)
Loading

0 comments on commit 6d1a928

Please sign in to comment.