… | |
… | |
265 | if (expect_false (res >> UVSIZE * 8 - 7)) |
265 | if (expect_false (res >> UVSIZE * 8 - 7)) |
266 | error ("BER variable length integer overflow"); |
266 | error ("BER variable length integer overflow"); |
267 | |
267 | |
268 | res = (res << 7) | (c & 0x7f); |
268 | res = (res << 7) | (c & 0x7f); |
269 | |
269 | |
270 | if (!(c & 0x80)) |
270 | if (expect_true (!(c & 0x80))) |
271 | return res; |
271 | return res; |
272 | |
272 | |
273 | c = get_u8 (); |
273 | c = get_u8 (); |
274 | } |
274 | } |
275 | } |
275 | } |
… | |
… | |
277 | static UV |
277 | static UV |
278 | get_length (void) |
278 | get_length (void) |
279 | { |
279 | { |
280 | UV res = get_u8 (); |
280 | UV res = get_u8 (); |
281 | |
281 | |
282 | if (res & 0x80) |
282 | if (expect_false (res & 0x80)) |
283 | { |
283 | { |
284 | int cnt = res & 0x7f; |
284 | U8 cnt = res & 0x7f; |
|
|
285 | |
|
|
286 | // this genewrates quite ugly code, but the overhead |
|
|
287 | // of copying the bytes for these lengths is probably so high |
|
|
288 | // that a slightly inefficient get_length won't matter. |
|
|
289 | |
|
|
290 | if (expect_false (cnt == 0)) |
|
|
291 | error ("indefinite BER value lengths not supported"); |
|
|
292 | |
|
|
293 | if (expect_false (cnt > UVSIZE)) |
|
|
294 | error ("BER value length too long (must fit into UV) or BER reserved value in length (X.690 8.1.3.5)"); |
|
|
295 | |
|
|
296 | want (cnt); |
|
|
297 | |
285 | res = 0; |
298 | res = 0; |
286 | |
299 | do |
287 | switch (cnt) |
300 | res = (res << 8) | *cur++; |
288 | { |
301 | while (--cnt); |
289 | case 0: |
|
|
290 | error ("indefinite BER value lengths not supported"); |
|
|
291 | |
|
|
292 | case 0x7f: |
|
|
293 | error ("BER reserved value in length (X.690 8.1.3.5)"); |
|
|
294 | |
|
|
295 | default: |
|
|
296 | error ("BER value length too long (must fit into UV)"); |
|
|
297 | |
|
|
298 | #if UVSIZE > 4 |
|
|
299 | case 8: res = (res << 8) | get_u8 (); |
|
|
300 | case 7: res = (res << 8) | get_u8 (); |
|
|
301 | case 6: res = (res << 8) | get_u8 (); |
|
|
302 | case 5: res = (res << 8) | get_u8 (); |
|
|
303 | #endif |
|
|
304 | case 4: res = (res << 8) | get_u8 (); |
|
|
305 | case 3: res = (res << 8) | get_u8 (); |
|
|
306 | case 2: res = (res << 8) | get_u8 (); |
|
|
307 | case 1: res = (res << 8) | get_u8 (); |
|
|
308 | } |
|
|
309 | } |
302 | } |
310 | |
303 | |
311 | return res; |
304 | return res; |
312 | } |
305 | } |
313 | |
306 | |
… | |
… | |
547 | UV len = get_length (); |
540 | UV len = get_length (); |
548 | |
541 | |
549 | if (len != 4) |
542 | if (len != 4) |
550 | croak ("BER_TYPE_IPADDRESS type with invalid length %d encountered (RFC 2578 7.1.5)", len); |
543 | croak ("BER_TYPE_IPADDRESS type with invalid length %d encountered (RFC 2578 7.1.5)", len); |
551 | |
544 | |
552 | U8 c1 = get_u8 (); |
545 | U8 *data = get_n (4); |
553 | U8 c2 = get_u8 (); |
546 | res = newSVpvf ("%d.%d.%d.%d", data [0], data [1], data [2], data [3]); |
554 | U8 c3 = get_u8 (); |
|
|
555 | U8 c4 = get_u8 (); |
|
|
556 | |
|
|
557 | res = newSVpvf ("%d.%d.%d.%d", c1, c2, c3, c4); |
|
|
558 | } |
547 | } |
559 | break; |
548 | break; |
560 | |
549 | |
561 | case BER_TYPE_UCS2: |
550 | case BER_TYPE_UCS2: |
562 | res = decode_ucs (2); |
551 | res = decode_ucs (2); |
… | |
… | |
669 | } |
658 | } |
670 | |
659 | |
671 | static U8 * |
660 | static U8 * |
672 | put_length_at (UV val, U8 *cur) |
661 | put_length_at (UV val, U8 *cur) |
673 | { |
662 | { |
674 | if (val < 0x7fU) |
663 | if (val <= 0x7fU) |
675 | *cur++ = val; |
664 | *cur++ = val; |
676 | else |
665 | else |
677 | { |
666 | { |
678 | U8 *lenb = cur++; |
667 | U8 *lenb = cur++; |
679 | |
668 | |
… | |
… | |
695 | } |
684 | } |
696 | |
685 | |
697 | static void |
686 | static void |
698 | put_length (UV val) |
687 | put_length (UV val) |
699 | { |
688 | { |
700 | need (5 + val); |
689 | need (9 + val); |
701 | cur = put_length_at (val, cur); |
690 | cur = put_length_at (val, cur); |
702 | } |
691 | } |
703 | |
692 | |
704 | // return how many bytes the encoded length requires |
693 | // return how many bytes the encoded length requires |
705 | static int length_length (UV val) |
694 | static int length_length (UV val) |
706 | { |
695 | { |
707 | return val < 0x7fU |
696 | // use hashing with a DeBruin sequence, anyone? |
|
|
697 | return expect_true (val <= 0x7fU) |
708 | ? 1 |
698 | ? 1 |
709 | : 2 |
699 | : 2 |
710 | + (val > 0xffU) |
700 | + (val > 0x000000000000ffU) |
711 | + (val > 0xffffU) |
701 | + (val > 0x0000000000ffffU) |
712 | + (val > 0xffffffU) |
702 | + (val > 0x00000000ffffffU) |
713 | #if UVSIZE > 4 |
703 | #if UVSIZE > 4 |
714 | + (val > 0xffffffffU) |
704 | + (val > 0x000000ffffffffU) |
715 | + (val > 0xffffffffffU) |
705 | + (val > 0x0000ffffffffffU) |
716 | + (val > 0xffffffffffffU) |
706 | + (val > 0x00ffffffffffffU) |
717 | + (val > 0xffffffffffffffU) |
707 | + (val > 0xffffffffffffffU) |
718 | #endif |
708 | #endif |
719 | ; |
709 | ; |
720 | } |
710 | } |
721 | |
711 | |