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

randombit / botan / 27806188297

18 Jun 2026 04:12PM UTC coverage: 89.37% (-0.03%) from 89.397%
27806188297

push

github

web-flow
Merge pull request #5677 from randombit/jack/oid-names

Add OID::registered_name

111637 of 124915 relevant lines covered (89.37%)

10895907.86 hits per line

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

88.12
/src/tests/test_oid.cpp
1
/*
2
* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
3
*     2023,2024 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "tests.h"
9

10
#if defined(BOTAN_HAS_ASN1)
11
   #include <botan/asn1_obj.h>
12
   #include <botan/ber_dec.h>
13
   #include <botan/der_enc.h>
14
#endif
15

16
namespace Botan_Tests {
17

18
namespace {
19

20
#if defined(BOTAN_HAS_ASN1)
21

22
Test::Result test_OID_to_string() {
1✔
23
   /*
24
   See #2730 and #2237
25

26
   Certain locales format integers with thousands separators.  This
27
   caused a subtle bug which caused OID comparisons to fail because
28
   OID::to_string(), which used ostringstream, introduced a thousands
29
   separator when the OID component had a value >= 1000. But this
30
   only failed in certain locales (pt_BR was reported).
31

32
   Nominally C++ requires std::to_string to also be locale-respecting.
33
   But, libc++, libstdc++, and MSVC's STL library all implement
34
   std::to_string in a way that ignores locales, because adding locale
35
   support means std::to_string will be both slow and a serialization
36
   point. So as a stopgap we assume this behavior from std::to_string.
37

38
   Here we test the original issue of #2237 to verify it works. If
39
   the compiler implements std::to_string in a way that respects locale,
40
   *and* this test is run in a locale that uses thousands separators,
41
   then it will fail. Which is much better than a very subtle failure.
42
   However if it ever does fail then we must replace nearly every
43
   call to std::to_string with something else that ignores locale.
44
   */
45

46
   const Botan::OID oid{1, 2, 1000, 1001, 1002000};
1✔
47

48
   Test::Result result("OID::to_string");
1✔
49

50
   result.test_str_eq("OID::to_string behaves as we expect", oid.to_string(), "1.2.1000.1001.1002000");
1✔
51
   result.test_str_eq(
1✔
52
      "OID::to_formatted_string falls back to dotted decimal", oid.to_formatted_string(), oid.to_string());
2✔
53

54
   return result;
1✔
55
}
1✔
56

57
Test::Result test_oid_registration() {
1✔
58
   Test::Result result("OID add");
1✔
59

60
   const std::string name = "botan-test-oid1";
1✔
61
   const Botan::OID oid("1.3.6.1.4.1.25258.1000.1");
1✔
62

63
   result.test_is_false("named OID not found", Botan::OID::from_name(name).has_value());
1✔
64

65
   Botan::OID::register_oid(oid, name);
1✔
66

67
   result.test_is_true("named OID found", Botan::OID::from_name(name).has_value());
1✔
68

69
   result.test_opt_str_eq("name of OID matches expected", oid.registered_name(), name);
2✔
70

71
   return result;
2✔
72
}
1✔
73

74
Test::Result test_add_and_lookup() {
1✔
75
   Test::Result result("OID add with redundant entries");
1✔
76

77
   const std::string name = "botan-test-oid2";
1✔
78
   const std::string name2 = "botan-test-oid2.2";
1✔
79
   const Botan::OID oid("1.3.6.1.4.1.25258.1001.1");
1✔
80
   const Botan::OID oid2("1.3.6.1.4.1.25258.1001.2");
1✔
81

82
   result.test_is_false("named OID not found", Botan::OID::from_name(name).has_value());
1✔
83

84
   Botan::OID::register_oid(oid, name);
1✔
85

86
   result.test_is_true("named OID found", Botan::OID::from_name(name).value_or(Botan::OID()) == oid);
2✔
87
   result.test_opt_str_eq("name of OID matches expected", oid.registered_name(), name);
2✔
88

89
   // completely redundant, nothing happens:
90
   Botan::OID::register_oid(oid, name);
1✔
91

92
   /*
93
   register a second OID to the same name; this is allowed but
94
   the name will still map back to the original OID
95
   */
96
   Botan::OID::register_oid(oid2, name);
1✔
97

98
   // name->oid map is unchanged:
99
   result.test_is_true("named OID found after second insert",
2✔
100
                       Botan::OID::from_name(name).value_or(Botan::OID()) == oid);
2✔
101
   result.test_opt_str_eq("name of OID matches expected", oid.registered_name(), name);
2✔
102
   // now second OID maps back to the string as expected:
103
   result.test_opt_str_eq("name of OID matches expected", oid2.registered_name(), name);
2✔
104

105
   try {
1✔
106
      Botan::OID::register_oid(oid2, name2);
1✔
107
      result.test_failure("Registration of second name to the same OID was accepted");
×
108
   } catch(Botan::Invalid_State&) {
1✔
109
      result.test_success("Registration of second name to the same OID fails");
1✔
110
   }
1✔
111

112
   const Botan::OID oid3("1.3.6.1.4.1.25258.1001.3");
1✔
113
   result.test_throws<Botan::Invalid_Argument>("Registration of an empty name is rejected",
1✔
114
                                               [&]() { Botan::OID::register_oid(oid3, ""); });
2✔
115
   result.test_is_false("OID with rejected empty name remains unregistered", oid3.registered_oid());
1✔
116

117
   return result;
2✔
118
}
1✔
119

120
class OID_Tests final : public Test {
1✔
121
   public:
122
      std::vector<Test::Result> run() override {
1✔
123
         std::vector<Test::Result> results;
1✔
124

125
         std::vector<std::function<Test::Result()>> fns = {
1✔
126
            test_OID_to_string,
127
            test_oid_registration,
128
            test_add_and_lookup,
129
         };
4✔
130

131
         for(size_t i = 0; i != fns.size(); ++i) {
4✔
132
            try {
3✔
133
               results.emplace_back(fns[i]());
6✔
134
            } catch(const std::exception& e) {
×
135
               results.emplace_back(Test::Result::Failure("OID tests " + std::to_string(i), e.what()));
×
136
            }
×
137
         }
138

139
         return results;
1✔
140
      }
2✔
141
};
142

143
BOTAN_REGISTER_TEST("asn1", "oid", OID_Tests);
144

145
class OID_Encoding_Tests : public Text_Based_Test {
×
146
   public:
147
      OID_Encoding_Tests() : Text_Based_Test("asn1_oid.vec", "OID,DER") {}
2✔
148

149
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
19✔
150
         const auto oid_str = vars.get_req_str("OID");
19✔
151
         const auto expected_der = vars.get_req_bin("DER");
19✔
152

153
         Test::Result result("OID DER encode/decode");
19✔
154

155
         const Botan::OID oid(oid_str);
19✔
156

157
         try {
19✔
158
            std::vector<uint8_t> der;
19✔
159
            Botan::DER_Encoder enc(der);
19✔
160
            enc.encode(oid);
19✔
161
            result.test_bin_eq("Encoding correct", der, expected_der);
19✔
162
         } catch(std::exception& e) {
19✔
163
            result.test_failure("Encoding OID failed", e.what());
×
164
         }
×
165

166
         try {
19✔
167
            Botan::BER_Decoder dec(expected_der, Botan::BER_Decoder::Limits::DER());
19✔
168
            Botan::OID dec_oid;
19✔
169
            dec.decode(dec_oid);
19✔
170
            dec.verify_end();
19✔
171
            result.test_str_eq("Decoding OID correct", dec_oid.to_string(), oid_str);
19✔
172
         } catch(std::exception& e) {
19✔
173
            result.test_failure("Decoding OID failed", e.what());
×
174
         }
×
175

176
         return result;
38✔
177
      }
19✔
178
};
179

180
BOTAN_REGISTER_TEST("asn1", "oid_enc", OID_Encoding_Tests);
181

182
class OID_Invalid_Encoding_Tests : public Text_Based_Test {
×
183
   public:
184
      OID_Invalid_Encoding_Tests() : Text_Based_Test("asn1_oid_invalid.vec", "DER") {}
1✔
185

186
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
15✔
187
         const auto test_der = vars.get_req_bin("DER");
15✔
188

189
         Test::Result result("OID DER decode invalid");
15✔
190

191
         try {
15✔
192
            Botan::BER_Decoder dec(test_der);
15✔
193
            Botan::OID oid;
15✔
194
            dec.decode(oid);
15✔
195
            dec.verify_end();
×
196
            result.test_failure("Accepted invalid OID encoding", oid.to_string());
×
197
         } catch(Botan::Decoding_Error&) {
45✔
198
            result.test_success("Rejected invalid OID with Decoding_Error");
15✔
199
         }
15✔
200

201
         return result;
15✔
202
      }
15✔
203
};
204

205
BOTAN_REGISTER_TEST("asn1", "oid_dec_invalid", OID_Invalid_Encoding_Tests);
206

207
#endif
208

209
}  // namespace
210

211
}  // 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