--- Convert-BER-XS/XS.xs 2019/04/20 14:09:56 1.14 +++ Convert-BER-XS/XS.xs 2019/04/20 15:23:26 1.15 @@ -10,7 +10,7 @@ enum { // ASN_TAG ASN_BOOLEAN = 0x01, - ASN_INTEGER32 = 0x02, + ASN_INTEGER = 0x02, ASN_BIT_STRING = 0x03, ASN_OCTET_STRING = 0x04, ASN_NULL = 0x05, @@ -193,7 +193,7 @@ int type; } *celem, default_map[] = { { ASN_UNIVERSAL, ASN_BOOLEAN , BER_TYPE_BOOL }, - { ASN_UNIVERSAL, ASN_INTEGER32 , BER_TYPE_INT }, + { ASN_UNIVERSAL, ASN_INTEGER , BER_TYPE_INT }, { ASN_UNIVERSAL, ASN_NULL , BER_TYPE_NULL }, { ASN_UNIVERSAL, ASN_OBJECT_IDENTIFIER, BER_TYPE_OID }, { ASN_UNIVERSAL, ASN_RELATIVE_OID , BER_TYPE_RELOID }, @@ -250,10 +250,10 @@ } // get ber-encoded integer (i.e. pack "w") -static U32 +static UV get_w (void) { - U32 res = 0; + UV res = 0; for (;;) { @@ -265,10 +265,10 @@ } } -static U32 +static UV get_length (void) { - U32 res = get_u8 (); + UV res = get_u8 (); if (res & 0x80) { @@ -285,6 +285,10 @@ error ("ASN.1 length too long"); return 0; + case 8: res = (res << 8) | get_u8 (); + case 7: res = (res << 8) | get_u8 (); + case 6: res = (res << 8) | get_u8 (); + case 5: res = (res << 8) | get_u8 (); case 4: res = (res << 8) | get_u8 (); case 3: res = (res << 8) | get_u8 (); case 2: res = (res << 8) | get_u8 (); @@ -298,11 +302,11 @@ static SV * decode_int (void) { - int len = get_length (); + UV len = get_length (); - if (len <= 0) + if (!len) { - error ("integer length equal to zero"); + error ("invalid integer length equal to zero"); return 0; } @@ -324,21 +328,20 @@ static SV * decode_data (void) { - U32 len = get_length (); - U8 *data = get_n (len); - return newSVpvn ((char *)data, len); + UV len = get_length (); + return newSVpvn ((char *)get_n (len), len); } -// gelper for decode_object_identifier +// helper for decode_object_identifier static char * -write_uv (char *buf, U32 u) +write_uv (char *buf, UV u) { // the one-digit case is absolutely predominant, so this pays off (hopefully) if (expect_true (u < 10)) *buf++ = u + '0'; else { - // this *could* be done much faster using branchless fixed-ppint arithmetics + // this *could* be done much faster using branchless fixed-point arithmetics char *beg = buf; do @@ -365,7 +368,7 @@ static SV * decode_oid (int relative) { - U32 len = get_length (); + UV len = get_length (); if (len <= 0) { @@ -374,7 +377,7 @@ } U8 *end = cur + len; - U32 w = get_w (); + UV w = get_w (); static char oid[MAX_OID_STRLEN]; // static, becaueds too large for stack char *app = oid; @@ -408,7 +411,7 @@ { SV *res = NEWSV (0, 0); - U32 len = get_length (); + UV len = get_length (); if (len & (chrsize - 1)) croak ("BER_TYPE_UCS has an invalid number of octets (%d)", len); @@ -457,8 +460,8 @@ if (constructed) { - U32 len = get_length (); - U32 seqend = (cur - buf) + len; + UV len = get_length (); + UV seqend = (cur - buf) + len; AV *av = (AV *)sv_2mortal ((SV *)newAV ()); while (cur < buf + seqend) @@ -474,7 +477,7 @@ { case BER_TYPE_NULL: { - U32 len = get_length (); + UV len = get_length (); if (len) croak ("BER_TYPE_NULL value with non-zero length %d encountered", len); @@ -485,7 +488,7 @@ case BER_TYPE_BOOL: { - U32 len = get_length (); + UV len = get_length (); if (len != 1) croak ("BER_TYPE_BOOLEAN value with invalid length %d encountered", len); @@ -517,7 +520,7 @@ case BER_TYPE_IPADDRESS: { - U32 len = get_length (); + UV len = get_length (); if (len != 4) croak ("BER_TYPE_IPADDRESS type with invalid length %d encountered", len); @@ -613,17 +616,24 @@ } static void -put_w_nocheck (U32 val) +put_w_nocheck (UV val) { - *cur = (val >> 7 * 4) | 0x80; cur += val >= (1 << (7 * 4)); - *cur = (val >> 7 * 3) | 0x80; cur += val >= (1 << (7 * 3)); - *cur = (val >> 7 * 2) | 0x80; cur += val >= (1 << (7 * 2)); - *cur = (val >> 7 * 1) | 0x80; cur += val >= (1 << (7 * 1)); +#if UVSIZE > 4 + *cur = (val >> 7 * 9) | 0x80; cur += val >= ((UV)1 << (7 * 9)); + *cur = (val >> 7 * 8) | 0x80; cur += val >= ((UV)1 << (7 * 8)); + *cur = (val >> 7 * 7) | 0x80; cur += val >= ((UV)1 << (7 * 7)); + *cur = (val >> 7 * 6) | 0x80; cur += val >= ((UV)1 << (7 * 6)); + *cur = (val >> 7 * 5) | 0x80; cur += val >= ((UV)1 << (7 * 5)); +#endif + *cur = (val >> 7 * 4) | 0x80; cur += val >= ((UV)1 << (7 * 4)); + *cur = (val >> 7 * 3) | 0x80; cur += val >= ((UV)1 << (7 * 3)); + *cur = (val >> 7 * 2) | 0x80; cur += val >= ((UV)1 << (7 * 2)); + *cur = (val >> 7 * 1) | 0x80; cur += val >= ((UV)1 << (7 * 1)); *cur = val & 0x7f; cur += 1; } static void -put_w (U32 val) +put_w (UV val) { need (5); // we only handle up to 5 bytes @@ -631,7 +641,7 @@ } static U8 * -put_length_at (U32 val, U8 *cur) +put_length_at (UV val, U8 *cur) { if (val < 0x7fU) *cur++ = val; @@ -639,6 +649,12 @@ { U8 *lenb = cur++; +#if UVSIZE > 4 + *cur = val >> 56; cur += *cur > 0; + *cur = val >> 48; cur += *cur > 0; + *cur = val >> 40; cur += *cur > 0; + *cur = val >> 32; cur += *cur > 0; +#endif *cur = val >> 24; cur += *cur > 0; *cur = val >> 16; cur += *cur > 0; *cur = val >> 8; cur += *cur > 0; @@ -651,18 +667,28 @@ } static void -put_length (U32 val) +put_length (UV val) { need (5 + val); cur = put_length_at (val, cur); } // return how many bytes the encoded length requires -static int length_length (U32 val) +static int length_length (UV val) { return val < 0x7fU ? 1 - : 2 + (val > 0xffU) + (val > 0xffffU) + (val > 0xffffffU); + : 2 + + (val > 0xffU) + + (val > 0xffffU) + + (val > 0xffffffU) +#if UVSIZE > 4 + + (val > 0xffffffffU) + + (val > 0xffffffffffU) + + (val > 0xffffffffffffU) + + (val > 0xffffffffffffffU) +#endif + ; } static void @@ -734,8 +760,8 @@ } // we don't know the length yet, so we optimistically -// assume the length will need one octet later. if that -// turns out to be wrong, we memove as needed. +// assume the length will need one octet later. If that +// turns out to be wrong, we memmove as needed. // mark the beginning static STRLEN len_fixup_mark (void) @@ -974,7 +1000,7 @@ } *civ, const_iv[] = { #define const_iv(name) { # name, name }, const_iv (ASN_BOOLEAN) - const_iv (ASN_INTEGER32) + const_iv (ASN_INTEGER) const_iv (ASN_BIT_STRING) const_iv (ASN_OCTET_STRING) const_iv (ASN_NULL) @@ -1092,7 +1118,7 @@ } void -ber_is_i32 (SV *tuple, SV *value = &PL_sv_undef) +ber_is_int (SV *tuple, SV *value = &PL_sv_undef) PPCODE: { if (!SvOK (tuple)) @@ -1100,14 +1126,14 @@ AV *av = ber_tuple (tuple); - IV data = SvIV (AvARRAY (av)[BER_DATA]); + UV data = SvUV (AvARRAY (av)[BER_DATA]); XPUSHs ( SvIV (AvARRAY (av)[BER_CLASS ]) == ASN_UNIVERSAL - && SvIV (AvARRAY (av)[BER_TAG ]) == ASN_INTEGER32 + && SvIV (AvARRAY (av)[BER_TAG ]) == ASN_INTEGER && !SvIV (AvARRAY (av)[BER_CONSTRUCTED]) - && (!SvOK (value) || data == SvIV (value)) - ? sv_2mortal (data ? newSViv (data) : newSVpv ("0 but true", 0)) + && (!SvOK (value) || data == SvUV (value)) + ? sv_2mortal (data ? newSVsv (AvARRAY (av)[BER_DATA]) : newSVpv ("0 but true", 0)) : &PL_sv_undef); } @@ -1146,15 +1172,15 @@ } SV * -ber_i32 (IV iv) +ber_int (SV *sv) CODE: { AV *av = newAV (); av_fill (av, BER_ARRAYSIZE - 1); AvARRAY (av)[BER_CLASS ] = newSVcacheint (ASN_UNIVERSAL); - AvARRAY (av)[BER_TAG ] = newSVcacheint (ASN_INTEGER32); + AvARRAY (av)[BER_TAG ] = newSVcacheint (ASN_INTEGER); AvARRAY (av)[BER_CONSTRUCTED] = newSVcacheint (0); - AvARRAY (av)[BER_DATA ] = newSViv (iv); + AvARRAY (av)[BER_DATA ] = newSVsv (sv); RETVAL = newRV_noinc ((SV *)av); } OUTPUT: RETVAL