Skip to content

Commit 29779b8

Browse files
committed
Test ip_representation building from string
1 parent ec2d5cb commit 29779b8

File tree

2 files changed

+268
-37
lines changed

2 files changed

+268
-37
lines changed

src/http_utils.cpp

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -352,38 +352,98 @@ ip_representation::ip_representation(const std::string& ip)
352352
{
353353
ip_version = http_utils::IPV6;
354354
parts = string_utilities::string_split(ip, ':', false);
355+
if (parts.size() > 8)
356+
{
357+
throw std::invalid_argument("IP is badly formatted. Max 8 parts in IPV6.");
358+
}
359+
360+
int omitted = 8 - (parts.size() - 1);
361+
if (omitted != 0)
362+
{
363+
int empty_count = 0;
364+
for (unsigned int i = 0; i < parts.size(); i++)
365+
{
366+
if (parts[i].size() == 0) empty_count++;
367+
}
368+
369+
if (empty_count > 1)
370+
{
371+
if (parts[parts.size() - 1].find(".") != std::string::npos) omitted -= 1;
372+
373+
if (empty_count == 2 && parts[0] == "" && parts[1] == "")
374+
{
375+
omitted += 1;
376+
parts = std::vector<std::string>(parts.begin() + 1, parts.end());
377+
}
378+
else
379+
{
380+
throw std::invalid_argument("IP is badly formatted. Cannot have more than one omitted segment in IPV6.");
381+
}
382+
}
383+
}
384+
355385
int y = 0;
356-
for(unsigned int i = 0; i < parts.size(); i++)
386+
for (unsigned int i = 0; i < parts.size(); i++)
357387
{
358-
if(parts[i] != "*" && parts[i] != "")
388+
if (parts[i] != "*")
359389
{
360-
if(parts[i].size() < 4)
390+
if (parts[i].size() == 0)
391+
{
392+
for (unsigned int omitted_idx = 0; omitted_idx < omitted; omitted_idx++)
393+
{
394+
pieces[y] = 0;
395+
pieces[y+1] = 0;
396+
y += 2;
397+
}
398+
399+
continue;
400+
}
401+
402+
if (parts[i].size() < 4)
361403
{
362404
stringstream ss;
363405
ss << setfill('0') << setw(4) << parts[i];
364406
parts[i] = ss.str();
365407
}
366-
if(parts[i].size() == 4)
408+
409+
if (parts[i].size() == 4)
367410
{
368411
pieces[y] = strtol((parts[i].substr(0,2)).c_str(),NULL,16);
369412
pieces[y+1] = strtol(
370413
(parts[i].substr(2,2)).c_str(),
371414
NULL,
372415
16
373416
);
417+
374418
y += 2;
375419
}
376420
else
377-
{
378-
if(y != 12)
379-
{
380-
throw std::invalid_argument("IP is badly formatted");
381-
}
421+
{
382422
if(parts[i].find('.') != std::string::npos)
383423
{
424+
if(y != 12)
425+
{
426+
throw std::invalid_argument("IP is badly formatted. Missing parts before nested IPV4.");
427+
}
428+
429+
if (i != parts.size() - 1)
430+
{
431+
throw std::invalid_argument("IP is badly formatted. Nested IPV4 should be at the end");
432+
}
433+
384434
vector<string> subparts = string_utilities::string_split(parts[i], '.');
385435
if(subparts.size() == 4)
386436
{
437+
for (unsigned int k = 0; k < 10; k++)
438+
{
439+
if (pieces[k] != 0) throw std::invalid_argument("IP is badly formatted. Nested IPV4 can be preceded only by 0 (and, optionally, two 255 octects)");
440+
}
441+
442+
if ((pieces[10] != 0 && pieces[10] != 255) || (pieces[11] != 0 && pieces[11] != 255))
443+
{
444+
throw std::invalid_argument("IP is badly formatted. Nested IPV4 can be preceded only by 0 (and, optionally, two 255 octects)");
445+
}
446+
387447
for(unsigned int ii = 0; ii < subparts.size(); ii++)
388448
{
389449
if(subparts[ii] != "*")
@@ -393,50 +453,30 @@ ip_representation::ip_representation(const std::string& ip)
393453
NULL,
394454
10
395455
);
456+
if (pieces[y+ii] > 255) throw std::invalid_argument("IP is badly formatted. 255 is max value for ip part.");
396457
}
397458
else
398459
{
399-
CLEAR_BIT(mask, y+11);
460+
CLEAR_BIT(mask, y+ii);
400461
}
401-
y++;
402462
}
403463
}
404464
else
405465
{
406-
throw std::invalid_argument("IP is badly formatted");
466+
throw std::invalid_argument("IP is badly formatted. Nested IPV4 can have max 4 parts.");
407467
}
408468
}
409469
else
410470
{
411-
throw std::invalid_argument("IP is badly formatted");
471+
throw std::invalid_argument("IP is badly formatted. IPV6 parts can have max 4 characters (or nest an IPV4)");
412472
}
413473
}
414474
}
415-
else if(parts[i] == "*")
475+
else
416476
{
417477
CLEAR_BIT(mask, y);
418478
y++;
419479
}
420-
else
421-
{
422-
if(parts.size() <= 8)
423-
{
424-
int covered_pieces = 1 + (8 - parts.size());
425-
if(parts[parts.size() - 1].find('.') != std::string::npos)
426-
{
427-
covered_pieces -= 2;
428-
}
429-
for(int k = 0; k < covered_pieces; k++)
430-
{
431-
pieces[y] = 0;
432-
y++;
433-
}
434-
}
435-
else
436-
{
437-
throw std::invalid_argument("IP is badly formatted");
438-
}
439-
}
440480
}
441481
}
442482
else //IPV4
@@ -450,6 +490,7 @@ ip_representation::ip_representation(const std::string& ip)
450490
if(parts[i] != "*")
451491
{
452492
pieces[12+i] = strtol(parts[i].c_str(), NULL, 10);
493+
if (pieces[12+i] > 255) throw std::invalid_argument("IP is badly formatted. 255 is max value for ip part.");
453494
}
454495
else
455496
{
@@ -459,7 +500,7 @@ ip_representation::ip_representation(const std::string& ip)
459500
}
460501
else
461502
{
462-
throw std::invalid_argument("IP is badly formatted");
503+
throw std::invalid_argument("IP is badly formatted. Max 4 parts in IPV4.");
463504
}
464505
}
465506
}

test/unit/http_utils_test.cpp

Lines changed: 192 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation4_str_invalid)
186186
LT_CHECK_THROW(http::ip_representation("192.168.5.5.5"));
187187
LT_END_AUTO_TEST(ip_representation4_str_invalid)
188188

189+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation4_str_beyond255)
190+
LT_CHECK_THROW(http::ip_representation("192.168.256.5"));
191+
LT_END_AUTO_TEST(ip_representation4_str_beyond255)
192+
189193
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str)
190194
http::ip_representation test_ip("2001:db8:8714:3a90::12");
191195

@@ -203,12 +207,198 @@ LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str)
203207
LT_CHECK_EQ(test_ip.pieces[9], 0);
204208
LT_CHECK_EQ(test_ip.pieces[10], 0);
205209
LT_CHECK_EQ(test_ip.pieces[11], 0);
206-
LT_CHECK_EQ(test_ip.pieces[12], 18);
210+
LT_CHECK_EQ(test_ip.pieces[12], 0);
207211
LT_CHECK_EQ(test_ip.pieces[13], 0);
208212
LT_CHECK_EQ(test_ip.pieces[14], 0);
209-
LT_CHECK_EQ(test_ip.pieces[15], 0);
213+
LT_CHECK_EQ(test_ip.pieces[15], 18);
214+
215+
LT_CHECK_EQ(test_ip.mask, 0xFFFF);
210216
LT_END_AUTO_TEST(ip_representation6_str)
211217

218+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_mask)
219+
http::ip_representation test_ip("2001:db8:8714:3a90:*:*");
220+
221+
LT_CHECK_EQ(test_ip.ip_version, http::http_utils::IPV6);
222+
223+
LT_CHECK_EQ(test_ip.pieces[0], 32);
224+
LT_CHECK_EQ(test_ip.pieces[1], 1);
225+
LT_CHECK_EQ(test_ip.pieces[2], 13);
226+
LT_CHECK_EQ(test_ip.pieces[3], 184);
227+
LT_CHECK_EQ(test_ip.pieces[4], 135);
228+
LT_CHECK_EQ(test_ip.pieces[5], 20);
229+
LT_CHECK_EQ(test_ip.pieces[6], 58);
230+
LT_CHECK_EQ(test_ip.pieces[7], 144);
231+
LT_CHECK_EQ(test_ip.pieces[8], 0);
232+
LT_CHECK_EQ(test_ip.pieces[9], 0);
233+
LT_CHECK_EQ(test_ip.pieces[10], 0);
234+
LT_CHECK_EQ(test_ip.pieces[11], 0);
235+
LT_CHECK_EQ(test_ip.pieces[12], 0);
236+
LT_CHECK_EQ(test_ip.pieces[13], 0);
237+
LT_CHECK_EQ(test_ip.pieces[14], 0);
238+
LT_CHECK_EQ(test_ip.pieces[15], 0);
239+
240+
LT_CHECK_EQ(test_ip.mask, 0xFCFF);
241+
LT_END_AUTO_TEST(ip_representation6_str_mask)
242+
243+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_nested)
244+
http::ip_representation test_ip("::ffff:192.0.2.128");
245+
246+
LT_CHECK_EQ(test_ip.ip_version, http::http_utils::IPV6);
247+
248+
LT_CHECK_EQ(test_ip.pieces[0], 0);
249+
LT_CHECK_EQ(test_ip.pieces[1], 0);
250+
LT_CHECK_EQ(test_ip.pieces[2], 0);
251+
LT_CHECK_EQ(test_ip.pieces[3], 0);
252+
LT_CHECK_EQ(test_ip.pieces[4], 0);
253+
LT_CHECK_EQ(test_ip.pieces[5], 0);
254+
LT_CHECK_EQ(test_ip.pieces[6], 0);
255+
LT_CHECK_EQ(test_ip.pieces[7], 0);
256+
LT_CHECK_EQ(test_ip.pieces[8], 0);
257+
LT_CHECK_EQ(test_ip.pieces[9], 0);
258+
LT_CHECK_EQ(test_ip.pieces[10], 255);
259+
LT_CHECK_EQ(test_ip.pieces[11], 255);
260+
LT_CHECK_EQ(test_ip.pieces[12], 192);
261+
LT_CHECK_EQ(test_ip.pieces[13], 0);
262+
LT_CHECK_EQ(test_ip.pieces[14], 2);
263+
LT_CHECK_EQ(test_ip.pieces[15], 128);
264+
265+
LT_CHECK_EQ(test_ip.mask, 0xFFFF);
266+
LT_END_AUTO_TEST(ip_representation6_str_nested)
267+
268+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_nested_deprecated)
269+
LT_CHECK_NOTHROW(http::ip_representation("::192.0.2.128"));
270+
http::ip_representation test_ip("::192.0.2.128");
271+
272+
LT_CHECK_EQ(test_ip.ip_version, http::http_utils::IPV6);
273+
274+
LT_CHECK_EQ(test_ip.pieces[0], 0);
275+
LT_CHECK_EQ(test_ip.pieces[1], 0);
276+
LT_CHECK_EQ(test_ip.pieces[2], 0);
277+
LT_CHECK_EQ(test_ip.pieces[3], 0);
278+
LT_CHECK_EQ(test_ip.pieces[4], 0);
279+
LT_CHECK_EQ(test_ip.pieces[5], 0);
280+
LT_CHECK_EQ(test_ip.pieces[6], 0);
281+
LT_CHECK_EQ(test_ip.pieces[7], 0);
282+
LT_CHECK_EQ(test_ip.pieces[8], 0);
283+
LT_CHECK_EQ(test_ip.pieces[9], 0);
284+
LT_CHECK_EQ(test_ip.pieces[10], 0);
285+
LT_CHECK_EQ(test_ip.pieces[11], 0);
286+
LT_CHECK_EQ(test_ip.pieces[12], 192);
287+
LT_CHECK_EQ(test_ip.pieces[13], 0);
288+
LT_CHECK_EQ(test_ip.pieces[14], 2);
289+
LT_CHECK_EQ(test_ip.pieces[15], 128);
290+
291+
LT_CHECK_EQ(test_ip.mask, 0xFFFF);
292+
LT_END_AUTO_TEST(ip_representation6_str_nested_deprecated)
293+
294+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_ipv4_mask)
295+
http::ip_representation test_ip("::ffff:192.0.*.*");
296+
297+
LT_CHECK_EQ(test_ip.ip_version, http::http_utils::IPV6);
298+
299+
LT_CHECK_EQ(test_ip.pieces[0], 0);
300+
LT_CHECK_EQ(test_ip.pieces[1], 0);
301+
LT_CHECK_EQ(test_ip.pieces[2], 0);
302+
LT_CHECK_EQ(test_ip.pieces[3], 0);
303+
LT_CHECK_EQ(test_ip.pieces[4], 0);
304+
LT_CHECK_EQ(test_ip.pieces[5], 0);
305+
LT_CHECK_EQ(test_ip.pieces[6], 0);
306+
LT_CHECK_EQ(test_ip.pieces[7], 0);
307+
LT_CHECK_EQ(test_ip.pieces[8], 0);
308+
LT_CHECK_EQ(test_ip.pieces[9], 0);
309+
LT_CHECK_EQ(test_ip.pieces[10], 255);
310+
LT_CHECK_EQ(test_ip.pieces[11], 255);
311+
LT_CHECK_EQ(test_ip.pieces[12], 192);
312+
LT_CHECK_EQ(test_ip.pieces[13], 0);
313+
LT_CHECK_EQ(test_ip.pieces[14], 0);
314+
LT_CHECK_EQ(test_ip.pieces[15], 0);
315+
316+
LT_CHECK_EQ(test_ip.mask, 0x3FFF);
317+
LT_END_AUTO_TEST(ip_representation6_str_ipv4_mask)
318+
319+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_clustered_middle)
320+
http::ip_representation test_ip("2001:db8::ff00:42:8329");
321+
322+
LT_CHECK_EQ(test_ip.ip_version, http::http_utils::IPV6);
323+
324+
LT_CHECK_EQ(test_ip.pieces[0], 32);
325+
LT_CHECK_EQ(test_ip.pieces[1], 1);
326+
LT_CHECK_EQ(test_ip.pieces[2], 13);
327+
LT_CHECK_EQ(test_ip.pieces[3], 184);
328+
LT_CHECK_EQ(test_ip.pieces[4], 0);
329+
LT_CHECK_EQ(test_ip.pieces[5], 0);
330+
LT_CHECK_EQ(test_ip.pieces[6], 0);
331+
LT_CHECK_EQ(test_ip.pieces[7], 0);
332+
LT_CHECK_EQ(test_ip.pieces[8], 0);
333+
LT_CHECK_EQ(test_ip.pieces[9], 0);
334+
LT_CHECK_EQ(test_ip.pieces[10], 255);
335+
LT_CHECK_EQ(test_ip.pieces[11], 0);
336+
LT_CHECK_EQ(test_ip.pieces[12], 0);
337+
LT_CHECK_EQ(test_ip.pieces[13], 66);
338+
LT_CHECK_EQ(test_ip.pieces[14], 131);
339+
LT_CHECK_EQ(test_ip.pieces[15], 41);
340+
341+
LT_CHECK_EQ(test_ip.mask, 0xFFFF);
342+
LT_END_AUTO_TEST(ip_representation6_str_clustered_middle)
343+
344+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_loopback)
345+
http::ip_representation test_ip("::1");
346+
347+
LT_CHECK_EQ(test_ip.ip_version, http::http_utils::IPV6);
348+
349+
LT_CHECK_EQ(test_ip.pieces[0], 0);
350+
LT_CHECK_EQ(test_ip.pieces[1], 0);
351+
LT_CHECK_EQ(test_ip.pieces[2], 0);
352+
LT_CHECK_EQ(test_ip.pieces[3], 0);
353+
LT_CHECK_EQ(test_ip.pieces[4], 0);
354+
LT_CHECK_EQ(test_ip.pieces[5], 0);
355+
LT_CHECK_EQ(test_ip.pieces[6], 0);
356+
LT_CHECK_EQ(test_ip.pieces[7], 0);
357+
LT_CHECK_EQ(test_ip.pieces[8], 0);
358+
LT_CHECK_EQ(test_ip.pieces[9], 0);
359+
LT_CHECK_EQ(test_ip.pieces[10], 0);
360+
LT_CHECK_EQ(test_ip.pieces[11], 0);
361+
LT_CHECK_EQ(test_ip.pieces[12], 0);
362+
LT_CHECK_EQ(test_ip.pieces[13], 0);
363+
LT_CHECK_EQ(test_ip.pieces[14], 0);
364+
LT_CHECK_EQ(test_ip.pieces[15], 1);
365+
366+
LT_CHECK_EQ(test_ip.mask, 0xFFFF);
367+
LT_END_AUTO_TEST(ip_representation6_str_loopback)
368+
369+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_invalid)
370+
LT_CHECK_THROW(http::ip_representation("2001:db8:8714:3a90::12:4:4:4"));
371+
LT_END_AUTO_TEST(ip_representation6_str_invalid)
372+
373+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_block_too_long)
374+
LT_CHECK_THROW(http::ip_representation("2001:db8:87214:3a90::12:4:4"));
375+
LT_END_AUTO_TEST(ip_representation6_str_block_too_long)
376+
377+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_invalid_multiple_clusters)
378+
LT_CHECK_THROW(http::ip_representation("2001::3a90::12:4:4"));
379+
LT_END_AUTO_TEST(ip_representation6_str_invalid_multiple_clusters)
380+
381+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_invalid_too_long_before_nested)
382+
LT_CHECK_THROW(http::ip_representation("2001:db8:8714:3a90:13:12:13:192.0.2.128"));
383+
LT_END_AUTO_TEST(ip_representation6_str_invalid_too_long_before_nested)
384+
385+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_invalid_nested_beyond255)
386+
LT_CHECK_THROW(http::ip_representation("::ffff:192.0.256.128"));
387+
LT_END_AUTO_TEST(ip_representation6_str_invalid_nested_beyond255)
388+
389+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_invalid_nested_not_at_end)
390+
LT_CHECK_THROW(http::ip_representation("::ffff:192.0.256.128:ffff"));
391+
LT_END_AUTO_TEST(ip_representation6_str_invalid_nested_not_at_end)
392+
393+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_invalid_nested_starting_non_zero)
394+
LT_CHECK_THROW(http::ip_representation("0:0:1::ffff:192.0.5.128"));
395+
LT_END_AUTO_TEST(ip_representation6_str_invalid_nested_starting_non_zero)
396+
397+
LT_BEGIN_AUTO_TEST(http_utils_suite, ip_representation6_str_invalid_nested_starting_wrong_prefix)
398+
LT_CHECK_THROW(http::ip_representation("::ffcc:192.0.5.128"));
399+
LT_CHECK_THROW(http::ip_representation("::ccff:192.0.5.128"));
400+
LT_END_AUTO_TEST(ip_representation6_str_invalid_nested_starting_wrong_prefix)
401+
212402
LT_BEGIN_AUTO_TEST_ENV()
213403
AUTORUN_TESTS()
214404
LT_END_AUTO_TEST_ENV()

0 commit comments

Comments
 (0)