1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdint.h>
6 
7 #include <limits>
8 #include <memory>
9 
10 #include "core/fxcodec/basic/basicmodule.h"
11 #include "core/fxcrt/fx_memory_wrappers.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
TEST(fxcodec,A85TestBadInputs)14 TEST(fxcodec, A85TestBadInputs) {
15   const uint8_t src_buf[] = {1, 2, 3, 4};
16   std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
17   uint32_t dest_size = 0;
18 
19   // Error codes, not segvs, should callers pass us a nullptr pointer.
20   EXPECT_FALSE(BasicModule::A85Encode(src_buf, &dest_buf, nullptr));
21   EXPECT_FALSE(BasicModule::A85Encode(src_buf, nullptr, &dest_size));
22   EXPECT_FALSE(BasicModule::A85Encode({}, &dest_buf, &dest_size));
23 }
24 
25 // No leftover bytes, just translate 2 sets of symbols.
TEST(fxcodec,A85TestBasic)26 TEST(fxcodec, A85TestBasic) {
27   // Make sure really big values don't break.
28   const uint8_t src_buf[] = {1, 2, 3, 4, 255, 255, 255, 255};
29   std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
30   uint32_t dest_size = 0;
31   EXPECT_TRUE(BasicModule::A85Encode(src_buf, &dest_buf, &dest_size));
32 
33   // Should have 5 chars for each set of 4 and 2 terminators.
34   const uint8_t expected_out[] = {33, 60, 78, 63, 43,  115,
35                                   56, 87, 45, 33, 126, 62};
36   ASSERT_EQ(FX_ArraySize(expected_out), dest_size);
37 
38   // Check the output
39   auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
40   for (uint32_t i = 0; i < dest_size; i++)
41     EXPECT_EQ(expected_out[i], dest_buf_span[i]) << " at " << i;
42 }
43 
44 // Leftover bytes.
TEST(fxcodec,A85TestLeftoverBytes)45 TEST(fxcodec, A85TestLeftoverBytes) {
46   std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
47   uint32_t dest_size = 0;
48 
49   {
50     // 1 Leftover Byte:
51     const uint8_t src_buf_1leftover[] = {1, 2, 3, 4, 255};
52     EXPECT_TRUE(
53         BasicModule::A85Encode(src_buf_1leftover, &dest_buf, &dest_size));
54 
55     // 5 chars for first symbol + 2 + 2 terminators.
56     uint8_t expected_out_1leftover[] = {33, 60, 78, 63, 43, 114, 114, 126, 62};
57     ASSERT_EQ(FX_ArraySize(expected_out_1leftover), dest_size);
58 
59     // Check the output
60     auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
61     for (uint32_t i = 0; i < dest_size; i++)
62       EXPECT_EQ(expected_out_1leftover[i], dest_buf_span[i]) << " at " << i;
63   }
64 
65   {
66     // 2 Leftover bytes:
67     const uint8_t src_buf_2leftover[] = {1, 2, 3, 4, 255, 254};
68     dest_buf.reset();
69     dest_size = 0;
70     EXPECT_TRUE(
71         BasicModule::A85Encode(src_buf_2leftover, &dest_buf, &dest_size));
72     // 5 chars for first symbol + 3 + 2 terminators.
73     const uint8_t expected_out_2leftover[] = {33,  60, 78, 63,  43,
74                                               115, 56, 68, 126, 62};
75     ASSERT_EQ(FX_ArraySize(expected_out_2leftover), dest_size);
76 
77     // Check the output
78     auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
79     for (uint32_t i = 0; i < dest_size; i++)
80       EXPECT_EQ(expected_out_2leftover[i], dest_buf_span[i]) << " at " << i;
81   }
82 
83   {
84     // 3 Leftover bytes:
85     const uint8_t src_buf_3leftover[] = {1, 2, 3, 4, 255, 254, 253};
86     dest_buf.reset();
87     dest_size = 0;
88     EXPECT_TRUE(
89         BasicModule::A85Encode(src_buf_3leftover, &dest_buf, &dest_size));
90     // 5 chars for first symbol + 4 + 2 terminators.
91     const uint8_t expected_out_3leftover[] = {33, 60, 78,  63,  43, 115,
92                                               56, 77, 114, 126, 62};
93     ASSERT_EQ(FX_ArraySize(expected_out_3leftover), dest_size);
94 
95     // Check the output
96     auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
97     for (uint32_t i = 0; i < dest_size; i++)
98       EXPECT_EQ(expected_out_3leftover[i], dest_buf_span[i]) << " at " << i;
99   }
100 }
101 
102 // Test all zeros comes through as "z".
TEST(fxcodec,A85TestZeros)103 TEST(fxcodec, A85TestZeros) {
104   std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
105   uint32_t dest_size = 0;
106 
107   {
108     // Make sure really big values don't break.
109     const uint8_t src_buf[] = {1, 2, 3, 4, 0, 0, 0, 0};
110     EXPECT_TRUE(BasicModule::A85Encode(src_buf, &dest_buf, &dest_size));
111 
112     // Should have 5 chars for first set of 4 + 1 for z + 2 terminators.
113     const uint8_t expected_out[] = {33, 60, 78, 63, 43, 122, 126, 62};
114     ASSERT_EQ(FX_ArraySize(expected_out), dest_size);
115 
116     // Check the output
117     auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
118     for (uint32_t i = 0; i < dest_size; i++)
119       EXPECT_EQ(expected_out[i], dest_buf_span[i]) << " at " << i;
120   }
121 
122   {
123     // Should also work if it is at the start:
124     const uint8_t src_buf_2[] = {0, 0, 0, 0, 1, 2, 3, 4};
125     dest_buf.reset();
126     dest_size = 0;
127     EXPECT_TRUE(BasicModule::A85Encode(src_buf_2, &dest_buf, &dest_size));
128 
129     // Should have 5 chars for set of 4 + 1 for z + 2 terminators.
130     const uint8_t expected_out_2[] = {122, 33, 60, 78, 63, 43, 126, 62};
131     ASSERT_EQ(FX_ArraySize(expected_out_2), dest_size);
132 
133     // Check the output
134     auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
135     for (uint32_t i = 0; i < dest_size; i++)
136       EXPECT_EQ(expected_out_2[i], dest_buf_span[i]) << " at " << i;
137   }
138 
139   {
140     // Try with 2 leftover zero bytes. Make sure we don't get a "z".
141     const uint8_t src_buf_3[] = {1, 2, 3, 4, 0, 0};
142     dest_buf.reset();
143     dest_size = 0;
144     EXPECT_TRUE(BasicModule::A85Encode(src_buf_3, &dest_buf, &dest_size));
145 
146     // Should have 5 chars for set of 4 + 3 for last 2 + 2 terminators.
147     const uint8_t expected_out_leftover[] = {33, 60, 78, 63,  43,
148                                              33, 33, 33, 126, 62};
149     ASSERT_EQ(FX_ArraySize(expected_out_leftover), dest_size);
150 
151     // Check the output
152     auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
153     for (uint32_t i = 0; i < dest_size; i++)
154       EXPECT_EQ(expected_out_leftover[i], dest_buf_span[i]) << " at " << i;
155   }
156 }
157 
158 // Make sure we get returns in the expected locations.
TEST(fxcodec,A85TestLineBreaks)159 TEST(fxcodec, A85TestLineBreaks) {
160   // Make sure really big values don't break.
161   uint8_t src_buf[131] = {0};
162   // 1 full line + most of a line of normal symbols.
163   for (int k = 0; k < 116; k += 4) {
164     src_buf[k] = 1;
165     src_buf[k + 1] = 2;
166     src_buf[k + 2] = 3;
167     src_buf[k + 3] = 4;
168   }
169   // Fill in the end, leaving an all zero gap + 3 extra zeros at the end.
170   for (int k = 120; k < 128; k++) {
171     src_buf[k] = 1;
172     src_buf[k + 1] = 2;
173     src_buf[k + 2] = 3;
174     src_buf[k + 3] = 4;
175   }
176   std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
177   uint32_t dest_size = 0;
178 
179   // Should succeed.
180   EXPECT_TRUE(BasicModule::A85Encode(src_buf, &dest_buf, &dest_size));
181 
182   // Should have 75 chars in the first row plus 2 char return,
183   // 76 chars in the second row plus 2 char return,
184   // and 9 chars in the last row with 2 terminators.
185   ASSERT_EQ(166u, dest_size);
186 
187   // Check for the returns.
188   auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
189   EXPECT_EQ(13, dest_buf_span[75]);
190   EXPECT_EQ(10, dest_buf_span[76]);
191   EXPECT_EQ(13, dest_buf_span[153]);
192   EXPECT_EQ(10, dest_buf_span[154]);
193 }
194