| /* |
| ** |
| ** Copyright 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 <android/hardware/confirmationui/support/cbor.h> |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <iomanip> |
| #include <iostream> |
| |
| #include <gtest/gtest.h> |
| |
| using namespace android::hardware::confirmationui::support; |
| |
| uint8_t testVector[] = { |
| 0xA4, 0x63, 0x6B, 0x65, 0x79, 0x65, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x63, 0x6B, 0x65, 0x79, 0x4D, |
| 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x31, 0x30, 0x00, 0x04, 0x07, 0x1B, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x07, 0x1A, 0xFD, 0x49, 0x8C, 0xFF, |
| 0xFF, 0x82, 0x69, 0xE2, 0x99, 0xA8, 0xE2, 0x9A, 0x96, 0xE2, 0xB6, 0x96, 0x59, 0x01, 0x91, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x00, |
| }; |
| |
| // 400 'a's and a '\0' |
| constexpr char fourHundredAs[] = |
| "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| "aaaaaaaaaaaaaaaaaaaaaaaa"; |
| |
| WriteState writeTest(WriteState state) { |
| return write(state, // |
| map( // |
| pair(text("key"), text("value")), // |
| pair(text("key"), bytes("100101010010")), // |
| pair(4, 7), // |
| pair((UINT64_C(1) << 62), INT64_C(-2000000000000000)) // |
| ), // |
| arr(text("♨⚖ⶖ"), bytes(fourHundredAs))); |
| } |
| |
| TEST(Cbor, FeatureTest) { |
| uint8_t buffer[0x1000]; |
| WriteState state(buffer); |
| state = writeTest(state); |
| ASSERT_EQ(sizeof(testVector), size_t(state.data_ - buffer)); |
| ASSERT_EQ(Error::OK, state.error_); |
| ASSERT_EQ(0, memcmp(buffer, testVector, sizeof(testVector))); |
| } |
| |
| // Test if in all write cases an out of data error is correctly propagated and we don't |
| // write beyond the end of the buffer. |
| TEST(Cbor, BufferTooShort) { |
| uint8_t buffer[0x1000]; |
| for (size_t s = 1; s < sizeof(testVector); ++s) { |
| memset(buffer, 0x22, 0x1000); // 0x22 is not in the testVector |
| WriteState state(buffer, s); |
| state = writeTest(state); |
| for (size_t t = s; t < 0x1000; ++t) { |
| ASSERT_EQ(0x22, buffer[t]); // check if a canary has been killed |
| } |
| ASSERT_EQ(Error::OUT_OF_DATA, state.error_); |
| } |
| } |
| |
| TEST(Cbor, MalformedUTF8Test_Stray) { |
| uint8_t buffer[20]; |
| WriteState state(buffer); |
| char malformed[] = {char(0x80), 0}; |
| state = write(state, text(malformed)); |
| ASSERT_EQ(Error::MALFORMED_UTF8, state.error_); |
| } |
| |
| TEST(Cbor, MalformendUTF8Test_StringEndsMidMultiByte) { |
| uint8_t buffer[20]; |
| WriteState state(buffer); |
| char malformed[] = {char(0xc0), 0}; |
| state = write(state, text(malformed)); |
| ASSERT_EQ(Error::MALFORMED_UTF8, state.error_); |
| } |
| |
| TEST(Cbor, UTF8Test_TwoBytes) { |
| uint8_t buffer[20]; |
| WriteState state(buffer); |
| char neat[] = {char(0xc3), char(0x82), 0}; |
| state = write(state, text(neat)); |
| ASSERT_EQ(Error::OK, state.error_); |
| } |
| |
| TEST(Cbor, UTF8Test_ThreeBytes) { |
| uint8_t buffer[20]; |
| WriteState state(buffer); |
| char neat[] = {char(0xe3), char(0x82), char(0x82), 0}; |
| state = write(state, text(neat)); |
| ASSERT_EQ(Error::OK, state.error_); |
| } |
| |
| TEST(Cbor, UTF8Test_FourBytes) { |
| uint8_t buffer[20]; |
| WriteState state(buffer); |
| char neat[] = {char(0xf3), char(0x82), char(0x82), char(0x82), 0}; |
| state = write(state, text(neat)); |
| ASSERT_EQ(Error::OK, state.error_); |
| } |
| |
| TEST(Cbor, MalformendUTF8Test_CharacterTooLong) { |
| uint8_t buffer[20]; |
| WriteState state(buffer); |
| char malformed[] = {char(0xf8), char(0x82), char(0x82), char(0x82), char(0x82), 0}; |
| state = write(state, text(malformed)); |
| ASSERT_EQ(Error::MALFORMED_UTF8, state.error_); |
| } |
| |
| TEST(Cbor, MalformendUTF8Test_StringEndsMidMultiByte2) { |
| uint8_t buffer[20]; |
| WriteState state(buffer); |
| char malformed[] = {char(0xc0), char(0x82), char(0x83), 0}; |
| state = write(state, text(malformed)); |
| ASSERT_EQ(Error::MALFORMED_UTF8, state.error_); |
| } |
| |
| TEST(Cbor, MinimalViableHeaderSizeTest) { |
| uint8_t buffer[20]; |
| WriteState state(buffer); |
| state = writeHeader(state, Type::NUMBER, 23); |
| ASSERT_EQ(state.data_ - buffer, 1); |
| |
| state = WriteState(buffer); |
| state = writeHeader(state, Type::NUMBER, 24); |
| ASSERT_EQ(state.data_ - buffer, 2); |
| |
| state = WriteState(buffer); |
| state = writeHeader(state, Type::NUMBER, 0xff); |
| ASSERT_EQ(state.data_ - buffer, 2); |
| |
| state = WriteState(buffer); |
| state = writeHeader(state, Type::NUMBER, 0x100); |
| ASSERT_EQ(state.data_ - buffer, 3); |
| |
| state = WriteState(buffer); |
| state = writeHeader(state, Type::NUMBER, 0xffff); |
| ASSERT_EQ(state.data_ - buffer, 3); |
| |
| state = WriteState(buffer); |
| state = writeHeader(state, Type::NUMBER, 0x10000); |
| ASSERT_EQ(state.data_ - buffer, 5); |
| |
| state = WriteState(buffer); |
| state = writeHeader(state, Type::NUMBER, 0xffffffff); |
| ASSERT_EQ(state.data_ - buffer, 5); |
| |
| state = WriteState(buffer); |
| state = writeHeader(state, Type::NUMBER, 0x100000000); |
| ASSERT_EQ(state.data_ - buffer, 9); |
| |
| state = WriteState(buffer); |
| state = writeHeader(state, Type::NUMBER, 0xffffffffffffffff); |
| ASSERT_EQ(state.data_ - buffer, 9); |
| } |