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

randombit / botan / 13212092742

08 Feb 2025 12:33AM UTC coverage: 91.658% (-0.004%) from 91.662%
13212092742

push

github

web-flow
Merge pull request #4642 from randombit/jack/target-info-header

Add internal target_info.h header

94839 of 103471 relevant lines covered (91.66%)

11295178.12 hits per line

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

88.51
/src/lib/math/bigint/big_code.cpp
1
/*
2
* BigInt Encoding/Decoding
3
* (C) 1999-2010,2012,2019,2021 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/bigint.h>
9

10
#include <botan/hex.h>
11
#include <botan/internal/divide.h>
12
#include <botan/internal/stl_util.h>
13

14
namespace Botan {
15

16
namespace {
17

18
consteval word decimal_conversion_radix() {
19
   if constexpr(sizeof(word) == 8) {
20
      return 10000000000000000000U;
21
   } else {
22
      return 1000000000U;
23
   }
24
}
25

26
consteval size_t decimal_conversion_radix_digits() {
27
   if constexpr(sizeof(word) == 8) {
28
      return 19;
29
   } else {
30
      return 9;
31
   }
32
}
33

34
}  // namespace
35

36
std::string BigInt::to_dec_string() const {
57✔
37
   constexpr word conversion_radix = decimal_conversion_radix();
57✔
38
   constexpr size_t radix_digits = decimal_conversion_radix_digits();
57✔
39
   // Use the largest power of 10 that fits in a word
40

41
   // (over-)estimate of the number of digits needed; log2(10) ~ 3.3219
42
   const size_t digit_estimate = static_cast<size_t>(1 + (this->bits() / 3.32));
57✔
43

44
   // (over-)estimate of db such that conversion_radix^db > *this
45
   const size_t digit_blocks = (digit_estimate + radix_digits - 1) / radix_digits;
57✔
46

47
   BigInt value = *this;
57✔
48
   value.set_sign(Positive);
57✔
49

50
   // Extract groups of digits into words
51
   std::vector<word> digit_groups(digit_blocks);
57✔
52

53
   for(size_t i = 0; i != digit_blocks; ++i) {
125✔
54
      word remainder = 0;
68✔
55
      ct_divide_word(value, conversion_radix, value, remainder);
68✔
56
      digit_groups[i] = remainder;
68✔
57
   }
58

59
   BOTAN_ASSERT_NOMSG(value.is_zero());
114✔
60

61
   // Extract digits from the groups
62
   std::vector<uint8_t> digits(digit_blocks * radix_digits);
57✔
63

64
   for(size_t i = 0; i != digit_blocks; ++i) {
125✔
65
      word remainder = digit_groups[i];
68✔
66
      for(size_t j = 0; j != radix_digits; ++j) {
1,360✔
67
         // Compiler should convert div/mod by 10 into mul by magic constant
68
         const word digit = remainder % 10;
1,292✔
69
         remainder /= 10;
1,292✔
70
         digits[radix_digits * i + j] = static_cast<uint8_t>(digit);
1,292✔
71
      }
72
   }
73

74
   // remove leading zeros
75
   while(!digits.empty() && digits.back() == 0) {
926✔
76
      digits.pop_back();
869✔
77
   }
78

79
   BOTAN_ASSERT_NOMSG(digit_estimate >= digits.size());
57✔
80

81
   // Reverse the digits to big-endian and format to text
82
   std::string s;
57✔
83
   s.reserve(1 + digits.size());
57✔
84

85
   if(is_negative()) {
57✔
86
      s += "-";
5✔
87
   }
88

89
   // Reverse and convert to textual digits
90
   for(auto i = digits.rbegin(); i != digits.rend(); ++i) {
480✔
91
      s.push_back(*i + '0');  // assumes ASCII
423✔
92
   }
93

94
   if(s.empty()) {
57✔
95
      s += "0";
6✔
96
   }
97

98
   return s;
114✔
99
}
114✔
100

101
std::string BigInt::to_hex_string() const {
84✔
102
   const size_t this_bytes = this->bytes();
84✔
103
   std::vector<uint8_t> bits(std::max<size_t>(1, this_bytes));
141✔
104

105
   if(this_bytes > 0) {
84✔
106
      this->serialize_to(bits);
82✔
107
   }
108

109
   std::string hrep;
84✔
110
   if(is_negative()) {
84✔
111
      hrep += "-";
5✔
112
   }
113
   hrep += "0x";
84✔
114
   hrep += hex_encode(bits);
168✔
115
   return hrep;
84✔
116
}
84✔
117

118
/*
119
* Encode two BigInt, with leading 0s if needed, and concatenate
120
*/
121
secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes) {
96✔
122
   if(n1.is_negative() || n2.is_negative()) {
96✔
123
      throw Encoding_Error("encode_fixed_length_int_pair: values must be positive");
×
124
   }
125
   if(n1.bytes() > bytes || n2.bytes() > bytes) {
96✔
126
      throw Encoding_Error("encode_fixed_length_int_pair: values too large to encode properly");
×
127
   }
128
   secure_vector<uint8_t> output(2 * bytes);
96✔
129
   BufferStuffer stuffer(output);
96✔
130
   n1.serialize_to(stuffer.next(bytes));
96✔
131
   n2.serialize_to(stuffer.next(bytes));
96✔
132
   return output;
96✔
133
}
×
134

135
BigInt BigInt::decode(std::span<const uint8_t> buf, Base base) {
×
136
   if(base == Binary) {
×
137
      return BigInt::from_bytes(buf);
×
138
   }
139
   return BigInt::decode(buf.data(), buf.size(), base);
×
140
}
141

142
/*
143
* Decode a BigInt
144
*/
145
BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base) {
46,594✔
146
   if(base == Binary) {
46,594✔
147
      return BigInt::from_bytes(std::span{buf, length});
×
148
   } else if(base == Hexadecimal) {
46,594✔
149
      BigInt r;
42,032✔
150
      secure_vector<uint8_t> binary;
42,032✔
151

152
      if(length % 2) {
42,032✔
153
         // Handle lack of leading 0
154
         const char buf0_with_leading_0[2] = {'0', static_cast<char>(buf[0])};
3,903✔
155

156
         binary = hex_decode_locked(buf0_with_leading_0, 2);
7,806✔
157

158
         if(length > 1) {
3,903✔
159
            binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]), length - 1, false);
6,090✔
160
         }
161
      } else {
162
         binary = hex_decode_locked(cast_uint8_ptr_to_char(buf), length, false);
76,258✔
163
      }
164

165
      r.assign_from_bytes(binary);
42,032✔
166
      return r;
42,032✔
167
   } else if(base == Decimal) {
46,594✔
168
      BigInt r;
4,562✔
169
      // This could be made faster using the same trick as to_dec_string
170
      for(size_t i = 0; i != length; ++i) {
383,602✔
171
         const char c = buf[i];
379,040✔
172

173
         if(c < '0' || c > '9') {
379,040✔
174
            throw Invalid_Argument("BigInt::decode: invalid decimal char");
×
175
         }
176

177
         const uint8_t x = c - '0';
379,040✔
178
         BOTAN_ASSERT_NOMSG(x < 10);
379,040✔
179

180
         r *= 10;
379,040✔
181
         r += x;
379,040✔
182
      }
183
      return r;
4,562✔
184
   } else {
4,562✔
185
      throw Invalid_Argument("Unknown BigInt decoding method");
×
186
   }
187
}
188

189
}  // namespace Botan
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