/*
**
** 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);
}