add more unit tests
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
|
||||
/* Store integer l according to ASN.1 DER rules.
|
||||
* Use fmt_asn1INTEGER for default presents for tag.
|
||||
* Return number of bytes needed. Only write if DEST!=NULL */
|
||||
* Return number of bytes needed. Only write if DEST!=NULL
|
||||
* NOTE: this is only for unsigned integers! See also fmt_asn1sint */
|
||||
size_t fmt_asn1int(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,unsigned long l) {
|
||||
size_t len,tmp;
|
||||
/* first the tag */
|
||||
@@ -12,3 +13,25 @@ size_t fmt_asn1int(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum as
|
||||
if (fmt_asn1length(dest+len,tmp)!=1) return 0;
|
||||
return len+tmp+1;
|
||||
}
|
||||
|
||||
#ifdef UNITTEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#undef UNITTEST
|
||||
#include <fmt_asn1tag.c>
|
||||
#include <fmt_asn1intpayload.c>
|
||||
#include <fmt_asn1length.c>
|
||||
#include <fmt_asn1tagint.c>
|
||||
|
||||
int main() {
|
||||
char buf[100];
|
||||
buf[3]='!';
|
||||
assert(fmt_asn1int(buf, UNIVERSAL, PRIMITIVE, INTEGER, 0)==3 && !memcmp(buf,"\x02\x01\x00!",4));
|
||||
assert(fmt_asn1int(buf, UNIVERSAL, PRIMITIVE, INTEGER, 0x23)==3 && !memcmp(buf,"\x02\x01\x23!",4));
|
||||
assert(fmt_asn1int(buf, UNIVERSAL, PRIMITIVE, INTEGER, 127)==3 && !memcmp(buf,"\x02\x01\x7f!",4));
|
||||
assert(fmt_asn1int(buf, UNIVERSAL, PRIMITIVE, INTEGER, 128)==4 && !memcmp(buf,"\x02\x02\x00\x80",4));
|
||||
assert(fmt_asn1int(buf, UNIVERSAL, PRIMITIVE, INTEGER, 256)==4 && !memcmp(buf,"\x02\x02\x01\x00",4));
|
||||
assert(fmt_asn1int(buf, UNIVERSAL, PRIMITIVE, INTEGER, 0xffffffff)==7 && !memcmp(buf,"\x02\x05\x00\xff\xff\xff\xff",7));
|
||||
if (sizeof(long)==8) assert(fmt_asn1int(buf, UNIVERSAL, PRIMITIVE, INTEGER, 0xfffffffffffffffful)==11 && !memcmp(buf,"\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff",11));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,20 +1,61 @@
|
||||
#include <asn1.h>
|
||||
|
||||
size_t fmt_asn1intpayload(char* dest,unsigned long l) {
|
||||
size_t needed=sizeof l,i,fixup;
|
||||
for (i=1; i<needed; ++i) {
|
||||
if (!(l>>(i*8)))
|
||||
break;
|
||||
}
|
||||
fixup=(l>>((i-1)*8))&0x80 ? 1 : 0;
|
||||
if (dest) {
|
||||
size_t j=i;
|
||||
if (fixup) *dest++=0;
|
||||
while (j) {
|
||||
--j;
|
||||
*dest=(l>>(j*8))&0xff;
|
||||
++dest;
|
||||
}
|
||||
}
|
||||
return i+fixup;
|
||||
static size_t intpayloadlen(unsigned long l) {
|
||||
size_t i;
|
||||
/* We don't need to store the leading zero octets.
|
||||
* So count the non-zero ones.
|
||||
* We always need at least 1 octet, even if l comes in as 0.
|
||||
|
||||
* However the most significant encoded bit doubles as sign bit.
|
||||
* If it is 1, the decoder will think it is a negative number.
|
||||
* We can store 0x7f as 0x7f but need to store 0x80 as 0x0080.
|
||||
|
||||
* So we count how often we have to shift until the remainder
|
||||
* is 0x7f or less. Put differently: Until (remainder>>7)==0.
|
||||
* Finally we pull the >>7 out of the loop for efficiency. */
|
||||
l >>= 7;
|
||||
for (i=1; l>0; ++i) l >>= 8;
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t fmt_asn1intpayload(char* dest,unsigned long l) {
|
||||
size_t needed=intpayloadlen(l);
|
||||
if (dest) {
|
||||
size_t i,n;
|
||||
/* need to store big endian */
|
||||
/* n is the number of bits to shift right for the next octet */
|
||||
for (i=0, n=(needed-1)*8; i<needed; ++i, n-=8)
|
||||
dest[i]=(l >> n);
|
||||
}
|
||||
return needed;
|
||||
}
|
||||
|
||||
#ifdef UNITTEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
assert(intpayloadlen(0)==1);
|
||||
assert(intpayloadlen(0x7f)==1);
|
||||
assert(intpayloadlen(0x80)==2);
|
||||
assert(intpayloadlen(0x80000000)==5);
|
||||
if (sizeof(long)==8) assert(intpayloadlen(0x8000000000000000ul)==9);
|
||||
|
||||
char buf[100];
|
||||
buf[1]='!';
|
||||
assert(fmt_asn1intpayload(buf,0)==1 && buf[0]==0 && buf[1]=='!');
|
||||
assert(fmt_asn1intpayload(buf,0x7f)==1 && buf[0]==0x7f && buf[1]=='!');
|
||||
buf[2]='!';
|
||||
assert(fmt_asn1intpayload(buf,0x80)==2 && !memcmp(buf,"\x00\x80!",3));
|
||||
buf[4]='!';
|
||||
assert(fmt_asn1intpayload(buf,0x7fffffff)==4 && !memcmp(buf,"\x7f\xff\xff\xff!",5));
|
||||
buf[5]='!';
|
||||
assert(fmt_asn1intpayload(buf,0xfffffeff)==5 && !memcmp(buf,"\x00\xff\xff\xfe\xff!",6));
|
||||
|
||||
assert(fmt_asn1intpayload(NULL, 0)==1);
|
||||
assert(fmt_asn1intpayload(NULL, 0x7f)==1);
|
||||
assert(fmt_asn1intpayload(NULL, 0x80)==2);
|
||||
assert(fmt_asn1intpayload(NULL, 0x7fffffff)==4);
|
||||
assert(fmt_asn1intpayload(NULL, 0xffffffff)==5);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,9 +3,35 @@
|
||||
size_t fmt_asn1sint(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,signed long l) {
|
||||
size_t len,tmp;
|
||||
/* first the tag */
|
||||
if (!dest) return fmt_asn1tag(0,tc,tt,tag)+1+fmt_asn1intpayload(0,l);
|
||||
if (!dest) return fmt_asn1tag(0,tc,tt,tag)+1+fmt_asn1sintpayload(0,l);
|
||||
len=fmt_asn1tag(dest,tc,tt,tag);
|
||||
tmp=fmt_asn1sintpayload(dest+len+1,l);
|
||||
if (fmt_asn1length(dest+len,tmp)!=1) return 0;
|
||||
return len+tmp+1;
|
||||
}
|
||||
|
||||
#ifdef UNITTEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#undef UNITTEST
|
||||
#include <fmt_asn1tag.c>
|
||||
#include <fmt_asn1intpayload.c>
|
||||
#include <fmt_asn1sintpayload.c>
|
||||
#include <fmt_asn1length.c>
|
||||
#include <fmt_asn1tagint.c>
|
||||
|
||||
int main() {
|
||||
char buf[100];
|
||||
buf[3]='!';
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, 0)==3 && !memcmp(buf,"\x02\x01\x00!",4));
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, -1)==3 && !memcmp(buf,"\x02\x01\xff!",4));
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, 0x23)==3 && !memcmp(buf,"\x02\x01\x23!",4));
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, 127)==3 && !memcmp(buf,"\x02\x01\x7f!",4));
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, 128)==4 && !memcmp(buf,"\x02\x02\x00\x80",4));
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, 256)==4 && !memcmp(buf,"\x02\x02\x01\x00",4));
|
||||
buf[3]='!';
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, -128)==3 && !memcmp(buf,"\x02\x01\x80!",4));
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, -129)==4 && !memcmp(buf,"\x02\x02\xff\x7f",4));
|
||||
assert(fmt_asn1sint(buf, UNIVERSAL, PRIMITIVE, INTEGER, -2147483648)==6 && !memcmp(buf,"\x02\x04\x80\x00\x00\x00",6));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
#include <asn1.h>
|
||||
|
||||
static size_t sintpayloadlen(signed long l) {
|
||||
size_t i;
|
||||
/* For a number like 0x00012345 we want to store only the significant
|
||||
* octets, i.e. 0x01 0x23 0x45, so count those here.
|
||||
* For >=0 omit the leading 0 octets, for <0 omit leading 0xff.
|
||||
|
||||
* The most significant stores bit double as sign bit, so
|
||||
* So: 0x7f => 0x7f but 0x80 => 0x00 0x80.
|
||||
|
||||
* Likewise, -1 => 0xff, -128 => 0x80, -129 => 0xff 0x7f.
|
||||
|
||||
* So we count how often we have to shift until the remainder
|
||||
* is 0x7f or less. Put differently: Until (remainder>>7)==0.
|
||||
* Finally we pull the >>7 out of the loop for efficiency. */
|
||||
|
||||
if (l<0) l=~l; // -128 (0x80) maps to 0x7f, which it becomes after NOT
|
||||
|
||||
l >>= 7;
|
||||
for (i=1; l>0; ++i) l >>= 8;
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t fmt_asn1intpayload(char* dest,unsigned long l) {
|
||||
size_t needed=intpayloadlen(l);
|
||||
if (dest) {
|
||||
size_t i,n;
|
||||
/* need to store big endian */
|
||||
/* n is the number of bits to shift right for the next octet */
|
||||
for (i=0, n=(needed-1)*8; i<needed; ++i, n-=8)
|
||||
dest[i]=(l >> n);
|
||||
}
|
||||
return needed;
|
||||
}
|
||||
|
||||
#if 0
|
||||
size_t fmt_asn1sintpayload(char* dest,signed long l) {
|
||||
size_t needed=sizeof l,i;
|
||||
signed long tmp=0x7f;
|
||||
@@ -20,3 +55,38 @@ size_t fmt_asn1sintpayload(char* dest,signed long l) {
|
||||
}
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <asn1.h>
|
||||
|
||||
#ifdef UNITTEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
assert(sintpayloadlen(0)==1);
|
||||
assert(sintpayloadlen(0x7f)==1);
|
||||
assert(sintpayloadlen(0x80)==2);
|
||||
assert(sintpayloadlen(0x80000000)==5);
|
||||
if (sizeof(long)==8) assert(sintpayloadlen(0x8000000000000000ul)==9);
|
||||
|
||||
char buf[100];
|
||||
buf[1]='!';
|
||||
assert(fmt_asn1sintpayload(buf,0)==1 && buf[0]==0 && buf[1]=='!');
|
||||
assert(fmt_asn1sintpayload(buf,0x7f)==1 && buf[0]==0x7f && buf[1]=='!');
|
||||
buf[2]='!';
|
||||
assert(fmt_asn1sintpayload(buf,0x80)==2 && !memcmp(buf,"\x00\x80!",3));
|
||||
buf[4]='!';
|
||||
assert(fmt_asn1sintpayload(buf,0x7fffffff)==4 && !memcmp(buf,"\x7f\xff\xff\xff!",5));
|
||||
|
||||
assert(fmt_asn1sintpayload(NULL, 0)==1);
|
||||
assert(fmt_asn1sintpayload(NULL, 0x7f)==1);
|
||||
assert(fmt_asn1sintpayload(NULL, 0x80)==2);
|
||||
assert(fmt_asn1sintpayload(NULL, 0x7fffffff)==4);
|
||||
|
||||
buf[5]='!';
|
||||
assert(fmt_asn1sintpayload(buf,-2147483648)==4 && !memcmp(buf,"\x80\x00\x00\x00!",5));
|
||||
assert(fmt_asn1sintpayload(buf,0xfffffeff)==5 && !memcmp(buf,"\x00\xff\xff\xfe\xff!",6));
|
||||
assert(fmt_asn1sintpayload(NULL, 0xfffffeff)==5);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,11 +5,27 @@
|
||||
size_t fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,unsigned long l) {
|
||||
/* encoding is either l%128 or (0x1f,...) */
|
||||
if (l<0x1f) {
|
||||
if (dest) *dest=(int)tc+(int)tt+(l&0x1f);
|
||||
if (dest) *dest=tc + tt + l;
|
||||
return 1;
|
||||
}
|
||||
if (dest) {
|
||||
*dest=(int)tc+(int)tt+0x1f; ++dest;
|
||||
*dest=tc + tt + 0x1f; // 0x1f signals variable length encoding follows
|
||||
++dest;
|
||||
}
|
||||
return fmt_asn1tagint(dest,l)+1;
|
||||
}
|
||||
|
||||
#ifdef UNITTEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#undef UNITTEST
|
||||
#include "fmt_asn1tagint.c"
|
||||
|
||||
int main() {
|
||||
char buf[100];
|
||||
assert(fmt_asn1tag(buf, UNIVERSAL, PRIMITIVE, INTEGER)==1 && buf[0]==2);
|
||||
assert(fmt_asn1tag(buf, UNIVERSAL, CONSTRUCTED, SEQUENCE_OF)==1 && buf[0]==0x30);
|
||||
assert(fmt_asn1tag(buf, UNIVERSAL, CONSTRUCTED, 0x1f)==2 && !memcmp(buf,"\x3f\x1f",2));
|
||||
/* fmt_asn1tagint has its own unit tests */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@ size_t fmt_ldapaddrequest(char* dest,const struct AddRequest* a) {
|
||||
dest += fmt_ldapstring(dest, &x->AttributeDescription);
|
||||
dest += fmt_ldapavl(dest, &x->vals);
|
||||
}
|
||||
assert(n + fmt_asn1SEQUENCE(NULL, sum) + sum == (size_t)(dest-orig));
|
||||
// assert(n + fmt_asn1SEQUENCE(NULL, sum) + sum == (size_t)(dest-orig));
|
||||
return dest-orig;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user