From 3b2203ddadae8b44ebe14a882274707ba58bc9c3 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 22 Jul 2016 16:13:20 -0700 Subject: aidl-cpp: Add support for hex values in const int Add support for hex values in 'const int' definitions in aidl. BUG: 26936964 TEST: Added/Ran unit tests & integration tests. Change-Id: I2e94a4f9a03b46eb02aae29120afc9e8f15e71c8 --- aidl.cpp | 2 ++ aidl_language.cpp | 24 +++++++++++++- aidl_language.h | 3 ++ aidl_language_l.ll | 3 ++ aidl_language_y.yy | 6 +++- aidl_unittest.cpp | 50 ++++++++++++++++++++++++++++++ tests/aidl_test_client_primitives.cpp | 10 +++++- tests/android/aidl/tests/ITestService.aidl | 4 +++ 8 files changed, 99 insertions(+), 3 deletions(-) diff --git a/aidl.cpp b/aidl.cpp index dea559a..513aaee 100644 --- a/aidl.cpp +++ b/aidl.cpp @@ -422,6 +422,8 @@ bool validate_constants(const AidlInterface& interface) { success = false; } names.insert(int_constant->GetName()); + // We've logged an error message for this on object construction. + success = success && int_constant->IsValid(); } for (const std::unique_ptr& string_constant : interface.GetStringConstants()) { diff --git a/aidl_language.cpp b/aidl_language.cpp index becca81..608c9f6 100644 --- a/aidl_language.cpp +++ b/aidl_language.cpp @@ -89,7 +89,29 @@ string AidlArgument::ToString() const { AidlIntConstant::AidlIntConstant(std::string name, int32_t value) : name_(name), - value_(value) {} + value_(value), + is_valid_(true) {} + +AidlIntConstant::AidlIntConstant(std::string name, + std::string value, + unsigned line_number) + : name_(name) { + char *end; + // Use long long to ensure 0xFFFFFFFF -> -1 works on 32 bit devices. + unsigned long long int long_value = std::strtoull(value.c_str(), &end, 16); + // Ensure that we parsed the string fully and the value fits in int32. + if ((*end != '\0') || + ((long_value == ULLONG_MAX) && (errno == ERANGE)) || + (long_value > std::numeric_limits::max())) { + is_valid_ = false; + LOG(ERROR) << "Found invalid int value '" << value + << "' on line " << line_number; + } else { + // Converting from unsigned long to signed integer. + value_ = long_value; + is_valid_ = true; + } +} AidlStringConstant::AidlStringConstant(std::string name, std::string value, diff --git a/aidl_language.h b/aidl_language.h index 5db8d85..43b8a9d 100644 --- a/aidl_language.h +++ b/aidl_language.h @@ -158,16 +158,19 @@ class AidlMember : public AidlNode { class AidlIntConstant : public AidlMember { public: AidlIntConstant(std::string name, int32_t value); + AidlIntConstant(std::string name, std::string value, unsigned line_number); virtual ~AidlIntConstant() = default; const std::string& GetName() const { return name_; } int GetValue() const { return value_; } + bool IsValid() const { return is_valid_; } AidlIntConstant* AsIntConstant() override { return this; } private: std::string name_; int32_t value_; + bool is_valid_; DISALLOW_COPY_AND_ASSIGN(AidlIntConstant); }; diff --git a/aidl_language_l.ll b/aidl_language_l.ll index b354481..a56758b 100644 --- a/aidl_language_l.ll +++ b/aidl_language_l.ll @@ -19,6 +19,7 @@ identifier [_a-zA-Z][_a-zA-Z0-9]* whitespace ([ \t\r]+) intvalue [-+]?(0|[1-9][0-9]*) +hexvalue 0[x|X][0-9a-fA-F]+ %% %{ @@ -90,6 +91,8 @@ oneway { yylval->token = new AidlToken("oneway", extra_text); } {intvalue} { yylval->integer = std::stoi(yytext); return yy::parser::token::INTVALUE; } +{hexvalue} { yylval->token = new AidlToken(yytext, extra_text); + return yy::parser::token::HEXVALUE; } /* syntax error! */ . { printf("UNKNOWN(%s)", yytext); diff --git a/aidl_language_y.yy b/aidl_language_y.yy index 888e6b9..4ad6754 100644 --- a/aidl_language_y.yy +++ b/aidl_language_y.yy @@ -37,7 +37,7 @@ int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *); AidlDocument* parcelable_list; } -%token IDENTIFIER INTERFACE ONEWAY C_STR +%token IDENTIFIER INTERFACE ONEWAY C_STR HEXVALUE %token INTVALUE %token '(' ')' ',' '=' '[' ']' '<' '>' '.' '{' '}' ';' @@ -192,6 +192,10 @@ constant_decl $$ = new AidlIntConstant($3->GetText(), $5); delete $3; } + | CONST INT identifier '=' HEXVALUE ';' { + $$ = new AidlIntConstant($3->GetText(), $5->GetText(), @5.begin.line); + delete $3; + } | CONST STRING identifier '=' C_STR ';' { $$ = new AidlStringConstant($3->GetText(), $5->GetText(), @5.begin.line); delete $3; diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp index 4677092..0d2ba53 100644 --- a/aidl_unittest.cpp +++ b/aidl_unittest.cpp @@ -282,6 +282,56 @@ TEST_F(AidlTest, FailOnDuplicateConstantNames) { EXPECT_EQ(AidlError::BAD_CONSTANTS, reported_error); } +TEST_F(AidlTest, FailOnMalformedConstHexValue) { + AidlError reported_error; + EXPECT_EQ(nullptr, + Parse("p/IFoo.aidl", + R"(package p; + interface IFoo { + const int BAD_HEX_VALUE = 0xffffffffffffffffff; + } + )", + &cpp_types_, + &reported_error)); + EXPECT_EQ(AidlError::BAD_CONSTANTS, reported_error); +} + +TEST_F(AidlTest, ParsePositiveConstHexValue) { + AidlError reported_error; + auto cpp_parse_result = + Parse("p/IFoo.aidl", + R"(package p; + interface IFoo { + const int POSITIVE_HEX_VALUE = 0xf5; + } + )", + &cpp_types_, + &reported_error); + EXPECT_NE(nullptr, cpp_parse_result); + const auto& cpp_int_constants = cpp_parse_result->GetIntConstants(); + EXPECT_EQ((size_t)1, cpp_int_constants.size()); + EXPECT_EQ("POSITIVE_HEX_VALUE", cpp_int_constants[0]->GetName()); + EXPECT_EQ(245, cpp_int_constants[0]->GetValue()); +} + +TEST_F(AidlTest, ParseNegativeConstHexValue) { + AidlError reported_error; + auto cpp_parse_result = + Parse("p/IFoo.aidl", + R"(package p; + interface IFoo { + const int NEGATIVE_HEX_VALUE = 0xffffffff; + } + )", + &cpp_types_, + &reported_error); + EXPECT_NE(nullptr, cpp_parse_result); + const auto& cpp_int_constants = cpp_parse_result->GetIntConstants(); + EXPECT_EQ((size_t)1, cpp_int_constants.size()); + EXPECT_EQ("NEGATIVE_HEX_VALUE", cpp_int_constants[0]->GetName()); + EXPECT_EQ(-1, cpp_int_constants[0]->GetValue()); +} + TEST_F(AidlTest, UnderstandsNativeParcelables) { io_delegate_.SetFileContents( "p/Bar.aidl", diff --git a/tests/aidl_test_client_primitives.cpp b/tests/aidl_test_client_primitives.cpp index 9142abd..6f70f43 100644 --- a/tests/aidl_test_client_primitives.cpp +++ b/tests/aidl_test_client_primitives.cpp @@ -73,7 +73,15 @@ bool ConfirmPrimitiveRepeat(const sp& s) { !RepeatPrimitive( s, &ITestService::RepeatInt, ITestService::TEST_CONSTANT7) || !RepeatPrimitive( - s, &ITestService::RepeatInt, ITestService::TEST_CONSTANT8) + s, &ITestService::RepeatInt, ITestService::TEST_CONSTANT8) || + !RepeatPrimitive( + s, &ITestService::RepeatInt, ITestService::TEST_CONSTANT9) || + !RepeatPrimitive( + s, &ITestService::RepeatInt, ITestService::TEST_CONSTANT10) || + !RepeatPrimitive( + s, &ITestService::RepeatInt, ITestService::TEST_CONSTANT11) || + !RepeatPrimitive( + s, &ITestService::RepeatInt, ITestService::TEST_CONSTANT12) ) { return false; } diff --git a/tests/android/aidl/tests/ITestService.aidl b/tests/android/aidl/tests/ITestService.aidl index c9efecb..4de6925 100644 --- a/tests/android/aidl/tests/ITestService.aidl +++ b/tests/android/aidl/tests/ITestService.aidl @@ -30,6 +30,10 @@ interface ITestService { const int TEST_CONSTANT6 = -0; const int TEST_CONSTANT7 = +0; const int TEST_CONSTANT8 = 0; + const int TEST_CONSTANT9 = 0x56; + const int TEST_CONSTANT10 = 0xa5; + const int TEST_CONSTANT11 = 0xFA; + const int TEST_CONSTANT12 = 0xffffffff; const String STRING_TEST_CONSTANT = "foo"; const String STRING_TEST_CONSTANT2 = "bar"; -- cgit v1.2.3