Fix bug found by fuzzer.

Also, add the demangle fuzzer code.

Test: Ran fuzzer, ran new unit tests.
Change-Id: If3e15e10af88b81602a8a0f0bfe071a015f6000b
This commit is contained in:
Christopher Ferris 2017-05-31 14:40:15 -07:00
parent b46fd68653
commit 15d2e42ceb
4 changed files with 79 additions and 4 deletions

32
demangle/Android.mk Normal file
View file

@ -0,0 +1,32 @@
#
# Copyright (C) 2017 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := demangle_fuzzer
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := \
Demangler.cpp \
demangle_fuzzer.cpp \
LOCAL_CFLAGS := \
-Wall \
-Werror \
-Wextra \
include $(BUILD_FUZZ_TEST)

View file

@ -22,7 +22,14 @@
#include "Demangler.h"
TEST(DemangleTest, VoidArgumentTest) {
TEST(DemangleTest, IllegalArgumentModifiers) {
Demangler demangler;
ASSERT_EQ("_Zpp4FUNKK", demangler.Parse("_Zpp4FUNKK"));
ASSERT_EQ("_Zpp4FUNVV", demangler.Parse("_Zpp4FUNVV"));
}
TEST(DemangleTest, VoidArgument) {
Demangler demangler;
ASSERT_EQ("func()", demangler.Parse("_ZN4funcEv"));

View file

@ -542,9 +542,8 @@ const char* Demangler::ParseArguments(const char* name) {
} else {
suffix = " volatile";
}
if (name[-1] == 'K' || name[-1] == 'V') {
if (!cur_state_.suffixes.empty() && (name[-1] == 'K' || name[-1] == 'V')) {
// Special case, const/volatile apply as a single entity.
assert(!cur_state_.suffixes.empty());
size_t index = cur_state_.suffixes.size();
cur_state_.suffixes[index-1].insert(0, suffix);
} else {
@ -723,7 +722,8 @@ std::string Demangler::Parse(const char* name, size_t max_length) {
&& static_cast<size_t>(cur_name - name) < max_length) {
cur_name = (this->*parse_func_)(cur_name);
}
if (cur_name == nullptr || *cur_name != '\0' || function_name_.empty()) {
if (cur_name == nullptr || *cur_name != '\0' || function_name_.empty() ||
!cur_state_.suffixes.empty()) {
return name;
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "Demangler.h"
extern "C" void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::vector<char> data_str(size + 1);
memcpy(data_str.data(), data, size);
data_str[size] = '\0';
Demangler demangler;
std::string demangled_name = demangler.Parse(data_str.data());
if (size != 0 && data_str[0] != '\0' && demangled_name.empty()) {
abort();
}
}