git.fiddlerwoaroof.com
Browse code

CJPM-5223: base32::decode validates input

Ed Langley authored on 14/06/2017 18:23:35
Showing 4 changed files
... ...
@@ -128,8 +128,10 @@ public:
128 128
     }
129 129
 
130 130
 private:
131
+    using reverse_map = std::unordered_map <char, unsigned char>;
132
+    using character_type = std::string::value_type;
131 133
 
132
-    std::unordered_map <char, unsigned char> construct_lookup_table() const
134
+    reverse_map construct_lookup_table() const
133 135
     {
134 136
         std::unordered_map<char, unsigned char> lookup_table;
135 137
 
... ...
@@ -188,6 +190,16 @@ private:
188 190
 
189 191
     }
190 192
 
193
+    uint8_t get_next_input(reverse_map &lookup_table, std::string &input, std::string::size_type idx) const {
194
+        character_type character = input[idx];
195
+
196
+        if (character != '=' && lookup_table.find(character) == lookup_table.end()) {
197
+            throw invalid_data_exception ();
198
+        }
199
+
200
+        return lookup_table[input[idx]];
201
+    }
202
+
191 203
 public:
192 204
 
193 205
     std::vector<uint8_t> decode (std::string input) const override
... ...
@@ -200,12 +212,10 @@ public:
200 212
         unsigned long long bits_written = 0;
201 213
 
202 214
         for (std::string::size_type idx = 0; idx < input.size(); idx++) {
203
-            // TODO: fail on invalid input
204
-            uint8_t val = lookup_table[input[idx]];
205
-
206 215
             uint8_t start_bit = bits_written % 8;
207 216
             std::vector<unsigned char>::size_type current_byte = bits_written/8;
208 217
 
218
+            uint8_t val = get_next_input(lookup_table, input, idx);
209 219
             set_vector_at_bit (result, val, current_byte, start_bit, 5);
210 220
 
211 221
             bits_written += 5;
... ...
@@ -221,4 +231,3 @@ template class std::vector<unsigned char>;
221 231
 base32::base32 ():
222 232
     delegate_ (std::make_shared<base32_impl> ())
223 233
 {}
224
-
... ...
@@ -16,6 +16,10 @@
16 16
 #include <vector>
17 17
 #include <string>
18 18
 
19
+class invalid_data_exception : public std::exception
20
+{
21
+};
22
+
19 23
 class base32_ifc
20 24
 {
21 25
 public:
... ...
@@ -44,4 +48,3 @@ public:
44 48
 };
45 49
 
46 50
 #endif
47
-
... ...
@@ -64,14 +64,24 @@ int decode_validates_input()
64 64
     // The token for key 76I6WTYEUTNCJUREMGKVM45PMA and time '2017/01/01 00:00:00' is 258675
65 65
     base32 codec = base32();
66 66
 
67
+    int num_exceptions = 0;
67 68
     try {
68
-        codec.decode ("\x00");
69
-        codec.decode ("\x00\x00\x00\x00\x00\x00\x00\x00\x00");
69
+        codec.decode ("A");
70
+        codec.decode ("AAAAAAAAA");
70 71
         fail ("invalid length should result in an exception");
71 72
     } catch (std::exception e) {
72
-        succeed();
73
+        num_exceptions++;
73 74
     }
74 75
 
76
+    try {
77
+        codec.decode ("--------");
78
+        fail ("invalid input characters should result in an exception");
79
+    } catch (invalid_data_exception) {
80
+        num_exceptions++;
81
+    }
82
+
83
+    check(num_exceptions == 2, "base32.decode should validate input data");
84
+
75 85
     succeed();
76 86
 }
77 87
 
... ...
@@ -107,4 +117,3 @@ int main (int argc, char *argv[])
107 117
 {
108 118
     return !run_tests();
109 119
 }
110
-
... ...
@@ -123,7 +123,7 @@ int installs_token()
123 123
 {
124 124
     //given
125 125
     std::string user_name ("user");
126
-    std::string key ("thekeyis");
126
+    std::string key ("THEKEYIS");
127 127
     std::string token ("thetoken");
128 128
     auto  test_tokens = std::make_shared<mock_tokens> (key);
129 129
     tokens tokens{test_tokens};
... ...
@@ -236,4 +236,3 @@ int main (int argc, char *argv[])
236 236
 {
237 237
     return !run_tests();
238 238
 }
239
-