• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 27253840577

08 Jun 2026 09:36PM UTC coverage: 89.367% (+0.01%) from 89.356%
27253840577

push

github

web-flow
Merge pull request #5657 from randombit/jack/ctrl-escaping

Escape control characters in codec error reporting and DN printing

110761 of 123940 relevant lines covered (89.37%)

11052282.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.25
/src/tests/test_codec.cpp
1
/*
2
* (C) 2015,2018,2021 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8

9
#include <botan/exceptn.h>
10
#include <botan/hex.h>
11

12
#if defined(BOTAN_HAS_BASE64_CODEC)
13
   #include <botan/base64.h>
14
#endif
15

16
#if defined(BOTAN_HAS_BASE32_CODEC)
17
   #include <botan/base32.h>
18
#endif
19

20
#if defined(BOTAN_HAS_BASE58_CODEC)
21
   #include <botan/base58.h>
22
#endif
23

24
namespace Botan_Tests {
25

26
namespace {
27

28
#if defined(BOTAN_HAS_BASE32_CODEC)
29

30
class Base32_Tests final : public Text_Based_Test {
×
31
   public:
32
      Base32_Tests() : Text_Based_Test("codec/base32.vec", "Base32", "Binary") {}
2✔
33

34
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
33✔
35
         Test::Result result("Base32");
33✔
36

37
         const bool is_valid = (type == "valid");
33✔
38
         const std::string base32 = vars.get_req_str("Base32");
33✔
39

40
         try {
33✔
41
            if(is_valid) {
33✔
42
               const std::vector<uint8_t> binary = vars.get_req_bin("Binary");
24✔
43
               result.test_bin_eq("base32 decoding", Botan::base32_decode(base32), binary);
24✔
44
               result.test_str_eq("base32 encoding", Botan::base32_encode(binary), base32);
24✔
45
            } else {
24✔
46
               auto res = Botan::base32_decode(base32);
9✔
47
               result.test_failure("decoded invalid base32 to " + Botan::hex_encode(res));
×
48
            }
×
49
         } catch(std::exception& e) {
9✔
50
            if(is_valid) {
9✔
51
               result.test_failure("rejected valid base32", e.what());
×
52
            } else {
53
               result.test_note("rejected invalid base32");
9✔
54
            }
55
         }
9✔
56

57
         return result;
33✔
58
      }
33✔
59

60
      std::vector<Test::Result> run_final_tests() override {
1✔
61
         Test::Result result("Base32");
1✔
62
         const std::string valid_b32 = "MY======";
1✔
63

64
         for(const char ws_char : {' ', '\t', '\r', '\n'}) {
5✔
65
            for(size_t i = 0; i <= valid_b32.size(); ++i) {
40✔
66
               std::string b32_ws = valid_b32;
36✔
67
               b32_ws.insert(i, 1, ws_char);
36✔
68

69
               try {
36✔
70
                  result.test_failure("decoded whitespace base32", Botan::base32_decode(b32_ws, false));
36✔
71
               } catch(std::exception&) {}
36✔
72

73
               try {
36✔
74
                  result.test_bin_eq("base32 decoding with whitespace", Botan::base32_decode(b32_ws, true), "66");
72✔
75
               } catch(std::exception& e) {
×
76
                  result.test_failure(b32_ws, e.what());
×
77
               }
×
78
            }
36✔
79
         }
80

81
         return {result};
3✔
82
      }
2✔
83
};
84

85
BOTAN_REGISTER_TEST("codec", "base32", Base32_Tests);
86

87
#endif
88

89
#if defined(BOTAN_HAS_BASE58_CODEC)
90

91
class Base58_Tests final : public Text_Based_Test {
×
92
   public:
93
      Base58_Tests() : Text_Based_Test("codec/base58.vec", "Base58", "Binary") {}
2✔
94

95
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
50✔
96
         Test::Result result("Base58");
50✔
97

98
         const bool is_valid = (type == "valid");
50✔
99
         const std::string base58 = vars.get_req_str("Base58");
50✔
100

101
         try {
50✔
102
            if(is_valid) {
50✔
103
               const std::vector<uint8_t> binary = vars.get_req_bin("Binary");
36✔
104
               result.test_bin_eq("base58 decoding", Botan::base58_decode(base58), binary);
36✔
105
               result.test_str_eq("base58 encoding", Botan::base58_encode(binary), base58);
36✔
106
            } else {
36✔
107
               auto res = Botan::base58_decode(base58);
14✔
108
               result.test_failure("decoded invalid base58 to " + Botan::hex_encode(res));
×
109
            }
×
110
         } catch(std::exception& e) {
14✔
111
            if(is_valid) {
14✔
112
               result.test_failure("rejected valid base58", e.what());
×
113
            } else {
114
               result.test_note("rejected invalid base58");
14✔
115
            }
116
         }
14✔
117

118
         return result;
50✔
119
      }
50✔
120
};
121

122
BOTAN_REGISTER_TEST("codec", "base58", Base58_Tests);
123

124
class Base58_Check_Tests final : public Text_Based_Test {
×
125
   public:
126
      Base58_Check_Tests() : Text_Based_Test("codec/base58c.vec", "Base58", "Binary") {}
2✔
127

128
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
9✔
129
         Test::Result result("Base58 Check");
9✔
130

131
         const bool is_valid = (type == "valid");
9✔
132
         const std::string base58 = vars.get_req_str("Base58");
9✔
133

134
         try {
9✔
135
            if(is_valid) {
9✔
136
               const std::vector<uint8_t> binary = vars.get_req_bin("Binary");
4✔
137
               result.test_bin_eq("base58 decoding", Botan::base58_check_decode(base58), binary);
4✔
138
               result.test_str_eq("base58 encoding", Botan::base58_check_encode(binary), base58);
4✔
139
            } else {
4✔
140
               auto res = Botan::base58_check_decode(base58);
5✔
141
               result.test_failure("decoded invalid base58c to " + Botan::hex_encode(res));
×
142
            }
×
143
         } catch(std::exception& e) {
5✔
144
            if(is_valid) {
5✔
145
               result.test_failure("rejected valid base58c", e.what());
×
146
            } else {
147
               result.test_note("rejected invalid base58c");
5✔
148
            }
149
         }
5✔
150

151
         return result;
9✔
152
      }
9✔
153
};
154

155
BOTAN_REGISTER_TEST("codec", "base58c", Base58_Check_Tests);
156

157
#endif
158

159
#if defined(BOTAN_HAS_BASE64_CODEC)
160

161
class Base64_Tests final : public Text_Based_Test {
×
162
   public:
163
      Base64_Tests() : Text_Based_Test("codec/base64.vec", "Base64", "Binary") {}
3✔
164

165
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
31✔
166
         Test::Result result("Base64");
31✔
167

168
         const bool is_valid = (type == "valid");
31✔
169
         const std::string base64 = vars.get_req_str("Base64");
31✔
170

171
         try {
31✔
172
            if(is_valid) {
31✔
173
               const std::vector<uint8_t> binary = vars.get_req_bin("Binary");
22✔
174
               result.test_bin_eq("base64 decoding", Botan::base64_decode(base64), binary);
22✔
175
               result.test_str_eq("base64 encoding", Botan::base64_encode(binary), base64);
22✔
176
            } else {
22✔
177
               auto res = Botan::base64_decode(base64);
9✔
178
               result.test_failure("decoded invalid base64 to " + Botan::hex_encode(res));
×
179
            }
×
180
         } catch(std::exception& e) {
9✔
181
            if(is_valid) {
9✔
182
               result.test_failure("rejected valid base64", e.what());
×
183
            } else {
184
               result.test_note("rejected invalid base64");
9✔
185
            }
186
         }
9✔
187

188
         return result;
31✔
189
      }
31✔
190

191
      std::vector<Test::Result> run_final_tests() override {
1✔
192
         Test::Result result("Base64");
1✔
193
         const std::string valid_b64 = "Zg==";
1✔
194

195
         for(const char ws_char : {' ', '\t', '\r', '\n'}) {
5✔
196
            for(size_t i = 0; i <= valid_b64.size(); ++i) {
24✔
197
               std::string b64_ws = valid_b64;
20✔
198
               b64_ws.insert(i, 1, ws_char);
20✔
199

200
               try {
20✔
201
                  result.test_failure("decoded whitespace base64", Botan::base64_decode(b64_ws, false));
20✔
202
               } catch(std::exception&) {}
20✔
203

204
               try {
20✔
205
                  result.test_bin_eq("base64 decoding with whitespace", Botan::base64_decode(b64_ws, true), "66");
40✔
206
               } catch(std::exception& e) {
×
207
                  result.test_failure(b64_ws, e.what());
×
208
               }
×
209
            }
20✔
210
         }
211

212
         return {result};
3✔
213
      }
2✔
214
};
215

216
BOTAN_REGISTER_TEST("codec", "base64", Base64_Tests);
217

218
#endif
219

220
class Codec_Error_Char_Display_Tests final : public Test {
1✔
221
   public:
222
      std::vector<Test::Result> run() override {
1✔
223
         Test::Result result("Codec error message character display");
1✔
224

225
         const std::vector<std::pair<char, std::string>> cases = {
1✔
226
            {'\x1b', "\\x1B"},
1✔
227
            {'\x00', "\\x00"},
1✔
228
            {'\n', "\\n"},
1✔
229
            {'\r', "\\r"},
1✔
230
            {'\t', "\\t"},
1✔
231
            {'\x7f', "\\x7F"},
1✔
232
            {static_cast<char>(0xFF), "\\xFF"},
1✔
233
         };
8✔
234

235
         for(const auto& [bad, expect] : cases) {
8✔
236
            try {
7✔
237
               Botan::hex_decode(std::string(1, bad), false);
14✔
238
               result.test_failure("hex_decode accepted invalid byte");
×
239
            } catch(const Botan::Invalid_Argument& e) {
7✔
240
               const std::string msg = e.what();
7✔
241
               result.test_is_true("message uses escaped string", msg.find(expect) != std::string::npos);
7✔
242
            }
7✔
243
         }
244

245
         return {result};
3✔
246
      }
3✔
247
};
248

249
BOTAN_REGISTER_TEST("codec", "codec_error_char_display", Codec_Error_Char_Display_Tests);
250

251
}  // namespace
252

253
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc