1/*
2**
3** Copyright 2017, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <android/hardware/confirmationui/support/cbor.h>
19
20#include <cstddef>
21#include <cstdint>
22#include <iomanip>
23#include <iostream>
24
25#include <gtest/gtest.h>
26
27using namespace android::hardware::confirmationui::support;
28
29uint8_t testVector[] = {
30    0xA4, 0x63, 0x6B, 0x65, 0x79, 0x65, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x63, 0x6B, 0x65, 0x79, 0x4D,
31    0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x31, 0x30, 0x00, 0x04, 0x07, 0x1B,
32    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x07, 0x1A, 0xFD, 0x49, 0x8C, 0xFF,
33    0xFF, 0x82, 0x69, 0xE2, 0x99, 0xA8, 0xE2, 0x9A, 0x96, 0xE2, 0xB6, 0x96, 0x59, 0x01, 0x91, 0x61,
34    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
35    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
36    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
37    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
38    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
39    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
40    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
41    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
42    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
43    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
44    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
45    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
46    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
47    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
48    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
49    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
50    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
51    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
52    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
53    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
54    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
55    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
56    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
57    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
58    0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x00,
59};
60
61// 400 'a's and a '\0'
62constexpr char fourHundredAs[] =
63    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
64    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
65    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
66    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
67    "aaaaaaaaaaaaaaaaaaaaaaaa";
68
69WriteState writeTest(WriteState state) {
70    return write(state,                                                     //
71                 map(                                                       //
72                     pair(text("key"), text("value")),                      //
73                     pair(text("key"), bytes("100101010010")),              //
74                     pair(4, 7),                                            //
75                     pair((UINT64_C(1) << 62), INT64_C(-2000000000000000))  //
76                     ),                                                     //
77                 arr(text("♨⚖ⶖ"), bytes(fourHundredAs)));
78}
79
80TEST(Cbor, FeatureTest) {
81    uint8_t buffer[0x1000];
82    WriteState state(buffer);
83    state = writeTest(state);
84    ASSERT_EQ(sizeof(testVector), size_t(state.data_ - buffer));
85    ASSERT_EQ(Error::OK, state.error_);
86    ASSERT_EQ(0, memcmp(buffer, testVector, sizeof(testVector)));
87}
88
89// Test if in all write cases an out of data error is correctly propagated and we don't
90// write beyond  the end of the buffer.
91TEST(Cbor, BufferTooShort) {
92    uint8_t buffer[0x1000];
93    for (size_t s = 1; s < sizeof(testVector); ++s) {
94        memset(buffer, 0x22, 0x1000);  // 0x22 is not in the testVector
95        WriteState state(buffer, s);
96        state = writeTest(state);
97        for (size_t t = s; t < 0x1000; ++t) {
98            ASSERT_EQ(0x22, buffer[t]);  // check if a canary has been killed
99        }
100        ASSERT_EQ(Error::OUT_OF_DATA, state.error_);
101    }
102}
103
104TEST(Cbor, MalformedUTF8Test_Stray) {
105    uint8_t buffer[20];
106    WriteState state(buffer);
107    char malformed[] = {char(0x80), 0};
108    state = write(state, text(malformed));
109    ASSERT_EQ(Error::MALFORMED_UTF8, state.error_);
110}
111
112TEST(Cbor, MalformendUTF8Test_StringEndsMidMultiByte) {
113    uint8_t buffer[20];
114    WriteState state(buffer);
115    char malformed[] = {char(0xc0), 0};
116    state = write(state, text(malformed));
117    ASSERT_EQ(Error::MALFORMED_UTF8, state.error_);
118}
119
120TEST(Cbor, UTF8Test_TwoBytes) {
121    uint8_t buffer[20];
122    WriteState state(buffer);
123    char neat[] = {char(0xc3), char(0x82), 0};
124    state = write(state, text(neat));
125    ASSERT_EQ(Error::OK, state.error_);
126}
127
128TEST(Cbor, UTF8Test_ThreeBytes) {
129    uint8_t buffer[20];
130    WriteState state(buffer);
131    char neat[] = {char(0xe3), char(0x82), char(0x82), 0};
132    state = write(state, text(neat));
133    ASSERT_EQ(Error::OK, state.error_);
134}
135
136TEST(Cbor, UTF8Test_FourBytes) {
137    uint8_t buffer[20];
138    WriteState state(buffer);
139    char neat[] = {char(0xf3), char(0x82), char(0x82), char(0x82), 0};
140    state = write(state, text(neat));
141    ASSERT_EQ(Error::OK, state.error_);
142}
143
144TEST(Cbor, MalformendUTF8Test_CharacterTooLong) {
145    uint8_t buffer[20];
146    WriteState state(buffer);
147    char malformed[] = {char(0xf8), char(0x82), char(0x82), char(0x82), char(0x82), 0};
148    state = write(state, text(malformed));
149    ASSERT_EQ(Error::MALFORMED_UTF8, state.error_);
150}
151
152TEST(Cbor, MalformendUTF8Test_StringEndsMidMultiByte2) {
153    uint8_t buffer[20];
154    WriteState state(buffer);
155    char malformed[] = {char(0xc0), char(0x82), char(0x83), 0};
156    state = write(state, text(malformed));
157    ASSERT_EQ(Error::MALFORMED_UTF8, state.error_);
158}
159
160TEST(Cbor, MinimalViableHeaderSizeTest) {
161    uint8_t buffer[20];
162    WriteState state(buffer);
163    state = writeHeader(state, Type::NUMBER, 23);
164    ASSERT_EQ(state.data_ - buffer, 1);
165
166    state = WriteState(buffer);
167    state = writeHeader(state, Type::NUMBER, 24);
168    ASSERT_EQ(state.data_ - buffer, 2);
169
170    state = WriteState(buffer);
171    state = writeHeader(state, Type::NUMBER, 0xff);
172    ASSERT_EQ(state.data_ - buffer, 2);
173
174    state = WriteState(buffer);
175    state = writeHeader(state, Type::NUMBER, 0x100);
176    ASSERT_EQ(state.data_ - buffer, 3);
177
178    state = WriteState(buffer);
179    state = writeHeader(state, Type::NUMBER, 0xffff);
180    ASSERT_EQ(state.data_ - buffer, 3);
181
182    state = WriteState(buffer);
183    state = writeHeader(state, Type::NUMBER, 0x10000);
184    ASSERT_EQ(state.data_ - buffer, 5);
185
186    state = WriteState(buffer);
187    state = writeHeader(state, Type::NUMBER, 0xffffffff);
188    ASSERT_EQ(state.data_ - buffer, 5);
189
190    state = WriteState(buffer);
191    state = writeHeader(state, Type::NUMBER, 0x100000000);
192    ASSERT_EQ(state.data_ - buffer, 9);
193
194    state = WriteState(buffer);
195    state = writeHeader(state, Type::NUMBER, 0xffffffffffffffff);
196    ASSERT_EQ(state.data_ - buffer, 9);
197}
198