Snap for 6001391 from 4797d5b58a1ec5592b4dd37531f65d7522fc9a4a to qt-aml-resolv-release
Change-Id: Iefa9f21d046ca5959df9b84765b7cebd9d08842b
diff --git a/Android.bp b/Android.bp
index fa5d485..9a59d4d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -110,7 +110,6 @@
"-Wextra",
"-Werror",
"-g",
- "-DUNIT_TEST",
],
srcs: [
@@ -134,20 +133,51 @@
"libaidl-common",
"libbase",
"libcutils",
+ "libgmock",
],
target: {
- host: {
- static_libs: ["libgmock_host"],
- },
android: {
static_libs: [
- "libgmock",
"liblog",
],
},
},
}
+cc_fuzz {
+ name: "aidl_parser_fuzzer",
+ host_supported: true,
+ dictionary: "tests/aidl_parser_fuzzer.dict",
+
+ fuzz_config: {
+ cc: [
+ "smoreland@google.com",
+ "jiyong@google.com",
+ "jeongik@google.com",
+ ],
+ },
+
+ srcs: [
+ "tests/aidl_parser_fuzzer.cpp",
+ "tests/fake_io_delegate.cpp",
+ "tests/test_util.cpp",
+ ],
+ static_libs: [
+ "libaidl-common",
+ "libbase",
+ "libcutils",
+ ],
+ target: {
+ android: {
+ static_libs: [
+ "liblog",
+ ],
+ },
+ },
+ // Enable this to show additional information about what is being parsed during fuzzing.
+ // cflags: ["-DFUZZ_LOG"],
+}
+
//
// Everything below here is used for integration testing of generated AIDL code.
//
diff --git a/aidl_const_expressions.cpp b/aidl_const_expressions.cpp
index 8214ac8..dbd1f8b 100644
--- a/aidl_const_expressions.cpp
+++ b/aidl_const_expressions.cpp
@@ -306,19 +306,23 @@
return new AidlConstantValue(location, Type::STRING, value);
}
-AidlConstantValue* AidlConstantValue::ShallowCopy(const AidlConstantValue& other) {
- switch (other.GetType()) {
- case Type::INT8: // fall-through
- case Type::INT32: // fall-through
- case Type::INT64:
- return Integral(
- AIDL_LOCATION_HERE,
- other.ValueString(AidlTypeSpecifier(AIDL_LOCATION_HERE, "long", false, nullptr, ""),
- AidlConstantValueDecorator));
- default:
- AIDL_FATAL(other) << "Unsupported type for ShallowCopy: " << ToString(other.GetType());
- return nullptr;
+AidlConstantValue* AidlConstantValue::ShallowIntegralCopy(const AidlConstantValue& other) {
+ // TODO(b/142894901): Perform full proper copy
+ AidlTypeSpecifier type = AidlTypeSpecifier(AIDL_LOCATION_HERE, "long", false, nullptr, "");
+ // TODO(b/142722772) CheckValid() should be called before ValueString()
+ if (!other.CheckValid()) {
+ AIDL_FATAL(other) << "Invalid value for ShallowIntegralCopy";
}
+ if (!other.evaluate(type)) {
+ AIDL_FATAL(other) << "Unsupported type for ShallowIntegralCopy: " << ToString(other.GetType());
+ }
+
+ AidlConstantValue* result =
+ Integral(AIDL_LOCATION_HERE, other.ValueString(type, AidlConstantValueDecorator));
+ if (result == nullptr) {
+ AIDL_FATAL(other) << "Unable to perform ShallowIntegralCopy.";
+ }
+ return result;
}
string AidlConstantValue::ValueString(const AidlTypeSpecifier& type,
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 945abc4..e27dbbe 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -769,7 +769,7 @@
enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
AIDL_LOCATION_HERE,
std::unique_ptr<AidlConstantValue>(
- AidlConstantValue::ShallowCopy(*previous->GetValue())),
+ AidlConstantValue::ShallowIntegralCopy(*previous->GetValue())),
"+",
std::unique_ptr<AidlConstantValue>(
AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1"))));
diff --git a/aidl_language.h b/aidl_language.h
index 6df25eb..ca2e359 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -399,9 +399,9 @@
// example: "\"asdf\""
static AidlConstantValue* String(const AidlLocation& location, const string& value);
- // Construct an AidlConstantValue by evaluating the other constant's value
- // string. This does not preserve the structure of the copied constant.
- static AidlConstantValue* ShallowCopy(const AidlConstantValue& other);
+ // Construct an AidlConstantValue by evaluating the other integral constant's
+ // value string. This does not preserve the structure of the copied constant.
+ static AidlConstantValue* ShallowIntegralCopy(const AidlConstantValue& other);
Type GetType() const { return final_type_; }
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index 79eb1a0..c9df5e8 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -18,6 +18,7 @@
#include "aidl_language.h"
#include "aidl_language_y.h"
#include "logging.h"
+#include <android-base/parseint.h>
#include <set>
#include <map>
#include <stdio.h>
@@ -158,7 +159,7 @@
%type<annotation_list>annotation_list
%type<type> type
%type<type> unannotated_type
-%type<arg_list> arg_list
+%type<arg_list> arg_list arg_non_empty_list
%type<arg> arg
%type<direction> direction
%type<type_args> type_args
@@ -212,10 +213,14 @@
decls
: decl {
- ps->AddDefinedType(unique_ptr<AidlDefinedType>($1));
+ if ($1 != nullptr) {
+ ps->AddDefinedType(unique_ptr<AidlDefinedType>($1));
+ }
}
| decls decl {
- ps->AddDefinedType(unique_ptr<AidlDefinedType>($2));
+ if ($2 != nullptr) {
+ ps->AddDefinedType(unique_ptr<AidlDefinedType>($2));
+ }
};
decl
@@ -223,12 +228,12 @@
{
$$ = $2;
- if ($1->size() > 0) {
+ if ($1->size() > 0 && $$ != nullptr) {
// copy comments from annotation to decl
- $2->SetComments($1->begin()->GetComments());
+ $$->SetComments($1->begin()->GetComments());
+ $$->Annotate(std::move(*$1));
}
- $$->Annotate(std::move(*$1));
delete $1;
}
;
@@ -307,7 +312,6 @@
ps->AddError();
$$ = nullptr;
delete $1;
- delete $2;
delete $4;
};
@@ -430,10 +434,9 @@
}
| '(' error ')'
{
- std::cerr << "ERROR: invalid const expression within parenthesis: "
- << $2->GetText() << " at " << @1 << ".\n";
- // to avoid segfaults
+ std::cerr << "ERROR: invalid const expression within parenthesis at " << @1 << ".\n";
ps->AddError();
+ // to avoid segfaults
$$ = AidlConstantValue::Integral(loc(@1), "0");
}
;
@@ -515,13 +518,23 @@
delete $4;
}
| type identifier '(' arg_list ')' '=' INTVALUE ';' {
- $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $1->GetComments(), std::stoi($7->GetText()));
+ int32_t serial;
+ if (!android::base::ParseInt($7->GetText(), &serial)) {
+ AIDL_ERROR(loc(@7)) << "Could not parse int value: " << $7->GetText();
+ ps->AddError();
+ }
+ $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $1->GetComments(), serial);
delete $2;
delete $7;
}
| annotation_list ONEWAY type identifier '(' arg_list ')' '=' INTVALUE ';' {
const std::string& comments = ($1->size() > 0) ? $1->begin()->GetComments() : $2->GetComments();
- $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments, std::stoi($9->GetText()));
+ int32_t serial;
+ if (!android::base::ParseInt($9->GetText(), &serial)) {
+ AIDL_ERROR(loc(@9)) << "Could not parse int value: " << $9->GetText();
+ ps->AddError();
+ }
+ $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments, serial);
$3->Annotate(std::move(*$1));
delete $1;
delete $2;
@@ -529,18 +542,22 @@
delete $9;
};
-arg_list
- :
- { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); }
- | arg {
+arg_non_empty_list
+ : arg {
$$ = new std::vector<std::unique_ptr<AidlArgument>>();
$$->push_back(std::unique_ptr<AidlArgument>($1));
}
- | arg_list ',' arg {
+ | arg_non_empty_list ',' arg {
$$ = $1;
$$->push_back(std::unique_ptr<AidlArgument>($3));
};
+arg_list
+ : /*empty*/
+ { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); }
+ | arg_non_empty_list { $$ = $1; }
+ ;
+
arg
: direction type identifier {
$$ = new AidlArgument(loc(@3), $1, $2, $3->GetText());
@@ -636,18 +653,20 @@
: ANNOTATION
{
$$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), nullptr);
- if ($$ == nullptr) {
+ if ($$) {
+ $$->SetComments($1->GetComments());
+ } else {
ps->AddError();
}
- $$->SetComments($1->GetComments());
delete $1;
};
| ANNOTATION '(' parameter_list ')' {
$$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), $3);
- if ($$ == nullptr) {
+ if ($$) {
+ $$->SetComments($1->GetComments());
+ } else {
ps->AddError();
}
- $$->SetComments($1->GetComments());
delete $1;
delete $3;
}
diff --git a/build/aidl_interface.go b/build/aidl_interface.go
index 6cca62b..56534e7 100644
--- a/build/aidl_interface.go
+++ b/build/aidl_interface.go
@@ -713,12 +713,10 @@
}
func (i *aidlInterface) currentVersion(ctx android.BaseModuleContext) string {
- if len(i.properties.Versions) == 0 {
+ if !i.hasVersion() {
return ""
} else {
- latestVersion := i.properties.Versions[len(i.properties.Versions)-1]
-
- i, err := strconv.Atoi(latestVersion)
+ i, err := strconv.Atoi(i.latestVersion())
if err != nil {
ctx.PropertyErrorf("versions", "must be integers")
return ""
@@ -728,16 +726,51 @@
}
}
+func (i *aidlInterface) latestVersion() string {
+ return i.properties.Versions[len(i.properties.Versions)-1]
+}
+func (i *aidlInterface) isLatestVersion(version string) bool {
+ if !i.hasVersion() {
+ return true
+ }
+ return version == i.latestVersion()
+}
+func (i *aidlInterface) hasVersion() bool {
+ return len(i.properties.Versions) > 0
+}
+
func (i *aidlInterface) isCurrentVersion(ctx android.BaseModuleContext, version string) bool {
return version == i.currentVersion(ctx)
}
+// This function returns module name with version. Assume that there is foo of which latest version is 2
+// Version -> Module name
+// "1"->foo-V1
+// "2"->foo-V2
+// "3"(unfrozen)->foo-unstable
+// ""-> foo
func (i *aidlInterface) versionedName(ctx android.BaseModuleContext, version string) string {
name := i.ModuleBase.Name()
- if !i.isCurrentVersion(ctx, version) {
- name = name + "-V" + version
+ if version == "" {
+ return name
}
- return name
+ if i.isCurrentVersion(ctx, version) {
+ return name + "-unstable"
+ }
+ return name + "-V" + version
+}
+
+// The only difference between versionedName and cppOutputName is about unstable version
+// foo-unstable -> foo-V3
+func (i *aidlInterface) cppOutputName(version string) string {
+ name := i.ModuleBase.Name()
+ if !i.hasVersion() {
+ return name
+ }
+ if version == "" {
+ version = i.latestVersion()
+ }
+ return name + "-V" + version
}
func (i *aidlInterface) srcsForVersion(mctx android.LoadHookContext, version string) (srcs []string, base string) {
@@ -784,9 +817,16 @@
currentVersion := i.currentVersion(mctx)
+ versionsForCpp := make([]string, len(i.properties.Versions))
+ copy(versionsForCpp, i.properties.Versions)
+ if i.hasVersion() {
+ // In C++ library, AIDL doesn't create the module of which name is with latest version,
+ // instead of it, there is a module without version.
+ versionsForCpp[len(i.properties.Versions)-1] = ""
+ }
if i.shouldGenerateCppBackend() {
libs = append(libs, addCppLibrary(mctx, i, currentVersion, langCpp))
- for _, version := range i.properties.Versions {
+ for _, version := range versionsForCpp {
addCppLibrary(mctx, i, version, langCpp)
}
}
@@ -795,20 +835,23 @@
// TODO(b/119771576): inherit properties and export 'is vendor' computation from cc.go
if !proptools.Bool(i.properties.Vendor_available) {
libs = append(libs, addCppLibrary(mctx, i, currentVersion, langNdk))
- for _, version := range i.properties.Versions {
+ for _, version := range versionsForCpp {
addCppLibrary(mctx, i, version, langNdk)
}
}
// TODO(b/121157555): combine with '-ndk' variant
libs = append(libs, addCppLibrary(mctx, i, currentVersion, langNdkPlatform))
- for _, version := range i.properties.Versions {
+ for _, version := range versionsForCpp {
addCppLibrary(mctx, i, version, langNdkPlatform)
}
}
-
+ versionsForJava := i.properties.Versions
+ if i.hasVersion() {
+ versionsForJava = append(i.properties.Versions, "")
+ }
if i.shouldGenerateJavaBackend() {
libs = append(libs, addJavaLibrary(mctx, i, currentVersion))
- for _, version := range i.properties.Versions {
+ for _, version := range versionsForJava {
addJavaLibrary(mctx, i, version)
}
}
@@ -825,7 +868,10 @@
func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
cppSourceGen := i.versionedName(mctx, version) + "-" + lang + "-source"
cppModuleGen := i.versionedName(mctx, version) + "-" + lang
-
+ cppOutputGen := i.cppOutputName(version) + "-" + lang
+ if i.hasVersion() && version == "" {
+ version = i.latestVersion()
+ }
srcs, base := i.srcsForVersion(mctx, version)
if len(srcs) == 0 {
// This can happen when the version is about to be frozen; the version
@@ -904,6 +950,7 @@
Stl: stl,
Cpp_std: cpp_std,
Cflags: append(addCflags, "-Wextra", "-Wall", "-Werror"),
+ Stem: proptools.StringPtr(cppOutputGen),
}, &i.properties.VndkProperties)
return cppModuleGen
@@ -912,7 +959,9 @@
func addJavaLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
javaSourceGen := i.versionedName(mctx, version) + "-java-source"
javaModuleGen := i.versionedName(mctx, version) + "-java"
-
+ if i.hasVersion() && version == "" {
+ version = i.latestVersion()
+ }
srcs, base := i.srcsForVersion(mctx, version)
if len(srcs) == 0 {
// This can happen when the version is about to be frozen; the version
diff --git a/build/properties.go b/build/properties.go
index b59db61..a1b3489 100644
--- a/build/properties.go
+++ b/build/properties.go
@@ -43,6 +43,7 @@
Stl *string
Cpp_std *string
Cflags []string
+ Stem *string
}
type javaProperties struct {
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index 4d8ed1e..fd6c9f0 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -1383,8 +1383,13 @@
ZERO,
ONE,
THREE = 3,
- FOUR = 4,
+ FOUR = 3 + 1,
FIVE,
+ SIX,
+ SEVEN,
+ EIGHT = 16 / 2,
+ NINE,
+ TEN,
})";
const char kExpectedEnumHeaderOutput[] =
@@ -1403,6 +1408,11 @@
THREE = 3,
FOUR = 4,
FIVE = 5,
+ SIX = 6,
+ SEVEN = 7,
+ EIGHT = 8,
+ NINE = 9,
+ TEN = 10,
};
} // namespace os
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index 60c93d6..fc9cc20 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -170,7 +170,11 @@
static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
const AidlDefinedType& defined_type) {
- out << "#include <android/binder_parcel_utils.h>\n";
+ out << "#include <cstdint>\n";
+ out << "#include <memory>\n";
+ out << "#include <optional>\n";
+ out << "#include <string>\n";
+ out << "#include <vector>\n";
out << "#ifdef BINDER_STABILITY_SUPPORT\n";
out << "#include <android/binder_stability.h>\n";
out << "#endif // BINDER_STABILITY_SUPPORT\n";
@@ -196,6 +200,8 @@
}
static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
const AidlDefinedType& /*defined_type*/) {
+ out << "#include <android/binder_parcel_utils.h>\n";
+
types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
if (a_defined_type.AsInterface() != nullptr) {
out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
diff --git a/options.cpp b/options.cpp
index 8bd2887..fa34a9d 100644
--- a/options.cpp
+++ b/options.cpp
@@ -39,7 +39,7 @@
string Options::GetUsage() const {
std::ostringstream sstr;
sstr << "usage:" << endl
- << myname_ << " --lang={java|cpp} [OPTION]... INPUT..." << endl
+ << myname_ << " --lang={java|cpp|ndk} [OPTION]... INPUT..." << endl
<< " Generate Java or C++ files for AIDL file(s)." << endl
<< endl
<< myname_ << " --preprocess OUTPUT INPUT..." << endl
diff --git a/tests/aidl_parser_fuzzer.cpp b/tests/aidl_parser_fuzzer.cpp
new file mode 100644
index 0000000..a3269ce
--- /dev/null
+++ b/tests/aidl_parser_fuzzer.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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 "aidl.h"
+#include "fake_io_delegate.h"
+#include "options.h"
+
+#include <iostream>
+
+#ifdef FUZZ_LOG
+constexpr bool kFuzzLog = true;
+#else
+constexpr bool kFuzzLog = false;
+#endif
+
+using android::aidl::test::FakeIoDelegate;
+
+void fuzz(uint8_t options, const std::string& content) {
+ uint8_t lang = options & 0x3;
+ std::string langOpt;
+ switch (lang) {
+ case 1:
+ langOpt = "cpp";
+ break;
+ case 2:
+ langOpt = "ndk";
+ break;
+ case 3:
+ langOpt = "java";
+ break;
+ default:
+ return;
+ }
+
+ // TODO: fuzz multiple files
+ // TODO: fuzz arguments
+ FakeIoDelegate io;
+ io.SetFileContents("a/path/Foo.aidl", content);
+
+ std::vector<std::string> args;
+ args.emplace_back("aidl");
+ args.emplace_back("--lang=" + langOpt);
+ args.emplace_back("-b");
+ args.emplace_back("-I .");
+ args.emplace_back("-o out");
+ // corresponding items also in aidl_parser_fuzzer.dict
+ args.emplace_back("a/path/Foo.aidl");
+
+ if (kFuzzLog) {
+ std::cout << "lang: " << langOpt << " content: " << content << std::endl;
+ }
+
+ int ret = android::aidl::compile_aidl(Options::From(args), io);
+ if (ret != 0) return;
+
+ if (kFuzzLog) {
+ for (const std::string& f : io.ListOutputFiles()) {
+ std::string output;
+ if (io.GetWrittenContents(f, &output)) {
+ std::cout << "OUTPUT " << f << ": " << std::endl;
+ std::cout << output << std::endl;
+ }
+ }
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size <= 1) return 0; // no use
+
+ uint8_t options = *data;
+ data++;
+ size--;
+
+ std::string content(reinterpret_cast<const char*>(data), size);
+ fuzz(options, content);
+
+ return 0;
+}
diff --git a/tests/aidl_parser_fuzzer.dict b/tests/aidl_parser_fuzzer.dict
new file mode 100644
index 0000000..1f882a0
--- /dev/null
+++ b/tests/aidl_parser_fuzzer.dict
@@ -0,0 +1,62 @@
+# keywords
+" parcelable "
+" import "
+" package "
+" in "
+" out "
+" inout "
+" cpp_header "
+" const "
+" true "
+" false "
+" interface "
+" oneway "
+" enum "
+
+# types
+" void "
+" boolean "
+" byte "
+" char "
+" int "
+" long "
+" float "
+" double "
+" String "
+" List "
+" Map "
+" IBinder "
+" FileDescriptor "
+" CharSequence "
+" ParcelFileDescriptor "
+" java.util.List "
+" java.util.Map "
+" android.os.ParcelFileDescriptor "
+
+# annotations
+" @nullable "
+" @utf8InCpp "
+" @VintfStability "
+" @UnsupportedAppUsage "
+" @SystemApi "
+" @JavaOnlyStableParcelable "
+" @Backing "
+" expectedSignature "
+" implicitMember "
+" maxTargetSdk "
+" publicAlternatives "
+" trackingBug "
+" type "
+
+# ignorable imports
+" android.os.IInterface "
+" android.os.IBinder "
+" android.os.Parcelable "
+" android.os.Parcel "
+" android.content.Context "
+" java.lang.String "
+
+# specific to fuzzer
+" a.path "
+" Foo "
+
diff --git a/tests/fake_io_delegate.cpp b/tests/fake_io_delegate.cpp
index 682ea57..dc35c4d 100644
--- a/tests/fake_io_delegate.cpp
+++ b/tests/fake_io_delegate.cpp
@@ -151,6 +151,14 @@
return true;
}
+std::vector<std::string> FakeIoDelegate::ListOutputFiles() {
+ std::vector<std::string> out;
+ for (const auto& [file, contents] : written_file_contents_) {
+ out.push_back(file);
+ }
+ return out;
+}
+
bool FakeIoDelegate::PathWasRemoved(const std::string& path) {
if (removed_files_.count(path) > 0) {
return true;
diff --git a/tests/fake_io_delegate.h b/tests/fake_io_delegate.h
index 68a9626..f077c0f 100644
--- a/tests/fake_io_delegate.h
+++ b/tests/fake_io_delegate.h
@@ -60,6 +60,7 @@
// Returns true iff we've previously written to |path|.
// When we return true, we'll set *contents to the written string.
bool GetWrittenContents(const std::string& path, std::string* content);
+ std::vector<std::string> ListOutputFiles();
bool PathWasRemoved(const std::string& path);