diff --git a/buffer.h b/buffer.h index 54bed5c..e51f394 100644 --- a/buffer.h +++ b/buffer.h @@ -13,6 +13,13 @@ extern "C" { #endif +/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ +#ifndef __writememsz__ +#define __writememsz__(a,b) +#define __readmemsz__(a,b) +#define __readmem__(a) +#endif + typedef struct buffer { char *x; /* actual buffer space */ size_t p; /* current position */ @@ -30,7 +37,9 @@ typedef struct buffer { #define BUFFER_INSIZE 8192 #define BUFFER_OUTSIZE 8192 +__writememsz__(4,5) void buffer_init(buffer* b,ssize_t (*op)(),int fd,char* y,size_t ylen); +__writememsz__(4,5) void buffer_init_free(buffer* b,ssize_t (*op)(),int fd,char* y,size_t ylen); void buffer_free(void* buf); void buffer_munmap(void* buf); @@ -38,11 +47,17 @@ int buffer_mmapread(buffer* b,const char* filename); void buffer_close(buffer* b); int buffer_flush(buffer* b); +__readmemsz__(2,3) int buffer_put(buffer* b,const char* x,size_t len); +__readmemsz__(2,3) int buffer_putalign(buffer* b,const char* x,size_t len); +__readmemsz__(2,3) int buffer_putflush(buffer* b,const char* x,size_t len); +__readmem__(2) int buffer_puts(buffer* b,const char* x); +__readmem__(2) int buffer_putsalign(buffer* b,const char* x); +__readmem__(2) int buffer_putsflush(buffer* b,const char* x); #if defined(__GNUC__) && !defined(__LIBOWFAT_INTERNAL) @@ -53,8 +68,8 @@ int buffer_putsflush(buffer* b,const char* x); #define buffer_putsflush(b,s) (__builtin_constant_p(s) ? buffer_putflush(b,s,strlen(s)) : buffer_putsflush(b,s)) #endif -int buffer_putm_internal(buffer*b,...); -int buffer_putm_internal_flush(buffer*b,...); +int buffer_putm_internal(buffer* b,...); +int buffer_putm_internal_flush(buffer* b,...); #define buffer_putm(b,...) buffer_putm_internal(b,__VA_ARGS__,(char*)0) #define buffer_putmflush(b,...) buffer_putm_internal_flush(b,__VA_ARGS__,(char*)0) @@ -67,16 +82,21 @@ int buffer_putnlflush(buffer* b); /* put \n and flush */ : buffer_put((s),&(c),1) \ ) +__writememsz__(2,3) ssize_t buffer_get(buffer* b,char* x,size_t len); ssize_t buffer_feed(buffer* b); ssize_t buffer_getc(buffer* b,char* x); +__writememsz__(2,3) ssize_t buffer_getn(buffer* b,char* x,size_t len); /* read bytes until the destination buffer is full (len bytes), end of * file is reached or the read char is in charset (setlen bytes). An * empty line when looking for \n will write '\n' to x and return 0. If * EOF is reached, \0 is written to the buffer */ +__writememsz__(2,3) +__readmemsz__(4,5) ssize_t buffer_get_token(buffer* b,char* x,size_t len,const char* charset,size_t setlen); +__writememsz__(2,3) ssize_t buffer_getline(buffer* b,char* x,size_t len); /* this predicate is given the string as currently read from the buffer @@ -84,6 +104,7 @@ ssize_t buffer_getline(buffer* b,char* x,size_t len); typedef int (*string_predicate)(const char* x,size_t len); /* like buffer_get_token but the token ends when your predicate says so */ +__writememsz__(2,3) ssize_t buffer_get_token_pred(buffer* b,char* x,size_t len,string_predicate p); char *buffer_peek(buffer* b); @@ -133,11 +154,13 @@ int buffer_putsaflush(buffer* b,const stralloc* sa); * data is available. */ /* read token from buffer to stralloc */ +__readmemsz__(3,4) int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen); /* read line from buffer to stralloc */ int buffer_getline_sa(buffer* b,stralloc* sa); /* same as buffer_get_token_sa but empty sa first */ +__readmemsz__(3,4) int buffer_get_new_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen); /* same as buffer_getline_sa but empty sa first */ int buffer_getnewline_sa(buffer* b,stralloc* sa); @@ -155,6 +178,7 @@ void buffer_fromsa(buffer* b,const stralloc* sa); /* read from sa */ int buffer_tosa(buffer*b,stralloc* sa); /* write to sa, auto-growing it */ #endif +__readmemsz__(2,3) void buffer_frombuf(buffer* b,const char* x,size_t l); /* buffer reads from static buffer */ #ifdef ARRAY_H diff --git a/byte.h b/byte.h index 0568164..9e9ba04 100644 --- a/byte.h +++ b/byte.h @@ -9,24 +9,36 @@ extern "C" { #endif +/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ #ifndef __pure__ #define __pure__ #endif +#ifndef __writememsz__ +#define __writememsz__(a,b) +#define __readmemsz__(a,b) +#endif + /* byte_chr returns the smallest integer i between 0 and len-1 * inclusive such that one[i] equals needle, or len if not found. */ +__readmemsz__(1,2) size_t byte_chr(const void* haystack, size_t len, char needle) __pure__; /* byte_rchr returns the largest integer i between 0 and len-1 inclusive * such that one[i] equals needle, or len if not found. */ +__readmemsz__(1,2) size_t byte_rchr(const void* haystack,size_t len,char needle) __pure__; /* byte_copy copies in[0] to out[0], in[1] to out[1], ... and in[len-1] * to out[len-1]. */ +__writememsz__(1,2) +__readmemsz__(3,2) void byte_copy(void* out, size_t len, const void* in); /* byte_copyr copies in[len-1] to out[len-1], in[len-2] to out[len-2], * ... and in[0] to out[0] */ +__writememsz__(1,2) +__readmemsz__(3,2) void byte_copyr(void* out, size_t len, const void* in); /* byte_diff returns negative, 0, or positive, depending on whether the @@ -34,13 +46,18 @@ void byte_copyr(void* out, size_t len, const void* in); * than, equal to, or greater than the string b[0], b[1], ..., * b[len-1]. When the strings are different, byte_diff does not read * bytes past the first difference. */ +__readmemsz__(1,2) +__readmemsz__(3,2) int byte_diff(const void* a, size_t len, const void* b) __pure__; /* byte_zero sets the bytes out[0], out[1], ..., out[len-1] to 0 */ +__writememsz__(1,2) void byte_zero(void* out, size_t len); #define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) +__readmemsz__(1,2) +__readmemsz__(3,2) int byte_equal_notimingattack(const void* a, size_t len,const void* b) __pure__; #if defined(__i386__) || defined(__x86_64__) diff --git a/scan.h b/scan.h index bcd4365..2458bfb 100644 --- a/scan.h +++ b/scan.h @@ -15,10 +15,16 @@ extern "C" { #endif +/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ #ifndef __pure__ #define __pure__ #endif +#ifndef __writememsz__ +#define __writememsz__(a,b) +#define __readmemsz__(a,b) +#endif + /* This file declared functions used to decode / scan / unmarshal * integer or string values from a buffer. * The first argument is always the source buffer, the second argument @@ -39,24 +45,28 @@ extern "C" { * values, i.e. on a 32-bit system: * scan_ulong("4294967296",&i" -> i=429496729, return 9 */ size_t scan_ulong(const char *src,unsigned long *dest); +__readmemsz__(1,2) size_t scan_ulongn(const char* src,size_t n,unsigned long* dest); /* Interpret src as ASCII hexadecimal number, write number to dest and * return the number of bytes that were parsed. * Note: leading '+' or '-' not accepted! */ size_t scan_xlong(const char *src,unsigned long *dest); +__readmemsz__(1,2) size_t scan_xlongn(const char *src,size_t n,unsigned long *dest); /* interpret src as ASCII octal number, write number to dest and * return the number of bytes that were parsed. * Note: leading '+' or '-' not accepted! */ size_t scan_8long(const char *src,unsigned long *dest); +__readmemsz__(1,2) size_t scan_8longn(const char *src,size_t n,unsigned long *dest); /* interpret src as signed ASCII decimal number, write number to dest * and return the number of bytes that were parsed. * Note: leading spaces not accepted! */ size_t scan_long(const char *src,signed long *dest); +__readmemsz__(1,2) size_t scan_longn(const char *src,size_t n,signed long *dest); size_t scan_longlong(const char *src,signed long long *dest); @@ -84,17 +94,21 @@ size_t scan_double(const char *in, double *dest); size_t scan_plusminus(const char *src,signed int *dest); /* return the highest integer n<=limit so that isspace(in[i]) for all 0<=i<=n */ +__readmemsz__(1,2) size_t scan_whitenskip(const char *in,size_t limit) __pure__; /* return the highest integer n<=limit so that !isspace(in[i]) for all 0<=i<=n */ +__readmemsz__(1,2) size_t scan_nonwhitenskip(const char *in,size_t limit) __pure__; /* return the highest integer n<=limit so that in[i] is element of * charset (ASCIIZ string) for all 0<=i<=n */ +__readmemsz__(1,3) size_t scan_charsetnskip(const char *in,const char *charset,size_t limit) __pure__; /* return the highest integer n<=limit so that in[i] is not element of * charset (ASCIIZ string) for all 0<=i<=n */ +__readmemsz__(1,3) size_t scan_noncharsetnskip(const char *in,const char *charset,size_t limit) __pure__; /* try to parse ASCII GMT date; does not understand time zones. */ @@ -153,6 +167,7 @@ size_t scan_pb_type5_fixed32(const char* in,size_t len,uint32_t* b) __pure__; * return 0 * Note: *dest will point inside the input buffer! */ +__readmemsz__(1,2) size_t scan_netstring(const char* in,size_t len,char** dest,size_t* slen) __pure__; /* internal function that might be useful independently */ diff --git a/scan/scan_8long.c b/scan/scan_8long.c index d44c750..46b6ff6 100644 --- a/scan/scan_8long.c +++ b/scan/scan_8long.c @@ -7,7 +7,7 @@ #endif size_t scan_8long(const char *src,unsigned long *dest) { - return scan_8longn(src,(size_t)-1,dest); + return scan_8longn(src,((size_t)-1)/2,dest); } #ifdef UNITTEST diff --git a/scan/scan_long.c b/scan/scan_long.c index 308721d..0a7a7a8 100644 --- a/scan/scan_long.c +++ b/scan/scan_long.c @@ -7,7 +7,7 @@ #endif size_t scan_long(const char *src,long *dest) { - return scan_longn(src,(size_t)(-1),dest); + return scan_longn(src,((size_t)-1)/2,dest); } #ifdef UNITTEST diff --git a/scan/scan_ulong.c b/scan/scan_ulong.c index 9323d35..d69f2a9 100644 --- a/scan/scan_ulong.c +++ b/scan/scan_ulong.c @@ -1,5 +1,5 @@ #include "scan.h" size_t scan_ulong(const char* src,unsigned long int* dest) { - return scan_ulongn(src,(size_t)-1,dest); + return scan_ulongn(src,((size_t)-1)/2,dest); } diff --git a/scan/scan_xlong.c b/scan/scan_xlong.c index 8cda884..314ba06 100644 --- a/scan/scan_xlong.c +++ b/scan/scan_xlong.c @@ -1,7 +1,7 @@ #include "scan.h" size_t scan_xlong(const char *src,unsigned long *dest) { - return scan_xlongn(src,(size_t)-1,dest); + return scan_xlongn(src,((size_t)-1)/2,dest); } /* unit tested via scan_xlongn */ diff --git a/stralloc.h b/stralloc.h index b328667..18a3f8b 100644 --- a/stralloc.h +++ b/stralloc.h @@ -8,10 +8,16 @@ extern "C" { #endif +/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ #ifndef __pure__ #define __pure__ #endif +#ifndef __writememsz__ +#define __writememsz__(a,b) +#define __readmemsz__(a,b) +#endif + /* stralloc is the internal data structure all functions are working on. * s is the string. * len is the used length of the string. @@ -46,6 +52,7 @@ int stralloc_readyplus(stralloc* sa,size_t len); /* stralloc_copyb copies the string buf[0], buf[1], ..., buf[len-1] into * sa, allocating space if necessary, and returns 1. If it runs out of * memory, stralloc_copyb leaves sa alone and returns 0. */ +__readmemsz__(2,3) int stralloc_copyb(stralloc* sa,const char* buf,size_t len); /* stralloc_copys copies a \0-terminated string from buf into sa, @@ -62,6 +69,7 @@ int stralloc_copy(stralloc* sa,const stralloc* sa2); * returns 1. If sa is unallocated, stralloc_catb is the same as * stralloc_copyb. If it runs out of memory, stralloc_catb leaves sa * alone and returns 0. */ +__readmemsz__(2,3) int stralloc_catb(stralloc* sa,const char* in,size_t len); /* stralloc_cats is analogous to stralloc_copys */ @@ -161,11 +169,13 @@ int buffer_putsaflush(buffer* b,const stralloc* sa); * data is available. */ /* read token from buffer to stralloc */ +__readmemsz__(3,4) int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen); /* read line from buffer to stralloc */ int buffer_getline_sa(buffer* b,stralloc* sa); /* same as buffer_get_token_sa but empty sa first */ +__readmemsz__(3,4) int buffer_get_new_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen); /* same as buffer_getline_sa but empty sa first */ int buffer_getnewline_sa(buffer* b,stralloc* sa); diff --git a/textcode.h b/textcode.h index beb296e..a09eff9 100644 --- a/textcode.h +++ b/textcode.h @@ -11,48 +11,72 @@ extern "C" { /* These take len bytes from src and write them in encoded form to * dest (if dest != NULL), returning the number of bytes written. */ +/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ +#ifndef __writememsz__ +#define __readmemsz__(a,b) +#endif + /* Needs len/3*4 bytes */ +__readmemsz__(2,3) size_t fmt_uuencoded(char* dest,const char* src,size_t len); /* Needs len/3*4 bytes */ +__readmemsz__(2,3) size_t fmt_base64(char* dest,const char* src,size_t len); +__readmemsz__(2,3) size_t fmt_base64url(char* dest,const char* src,size_t len); /* Worst case: len*3 */ +__readmemsz__(2,3) size_t fmt_quotedprintable(char* dest,const char* src,size_t len); /* Worst case: len*3 */ +__readmemsz__(2,3) size_t fmt_quotedprintable2(char* dest,const char* src,size_t len,const char* escapeme); /* Worst case: len*3 */ +__readmemsz__(2,3) size_t fmt_urlencoded(char* dest,const char* src,size_t len); /* Worst case: len*3 */ +__readmemsz__(2,3) size_t fmt_urlencoded2(char* dest,const char* src,size_t len,const char* escapeme); /* Worst case: len*2 */ +__readmemsz__(2,3) size_t fmt_yenc(char* dest,const char* src,size_t len); /* Needs len*2 bytes */ +__readmemsz__(2,3) size_t fmt_hexdump(char* dest,const char* src,size_t len); /* Change '<' to '<' and '&' to '&' and '\n' to '
'; worst case: len*5 */ /* This is meant for outputting text that goes between tags */ +__readmemsz__(2,3) size_t fmt_html(char* dest,const char* src,size_t len); /* Change '<' to '<' and '&' to '&' and '"' to '"'; worst case: len*6 */ /* This is meant for outputting text that goes in a tag argument between double quotes*/ +__readmemsz__(2,3) size_t fmt_html_tagarg(char* dest,const char* src,size_t len); /* Change '<' to '<' and '&' to '&'; worst case: len*5 */ +__readmemsz__(2,3) size_t fmt_xml(char* dest,const char* src,size_t len); /* Change '\' to "\\", '\n' to "\n", ^A to "\x01" etc; worst case: len*4 */ +__readmemsz__(2,3) size_t fmt_cescape(char* dest,const char* src,size_t len); /* Worst case: len*4 */ +__readmemsz__(2,3) size_t fmt_cescape2(char* dest,const char* src,size_t len,const char* escapeme); /* Fold whitespace to '_'; this is great for writing fields with * white spaces to a log file and still allow awk to do log analysis */ /* Worst case: same size */ +__readmemsz__(2,3) size_t fmt_foldwhitespace(char* dest,const char* src,size_t len); /* Worst case: len*3 */ +__readmemsz__(2,3) size_t fmt_ldapescape(char* dest,const char* src,size_t len); +__readmemsz__(2,3) size_t fmt_ldapescape2(char* dest,const char* src,size_t len,const char* escapeme); /* Encode JSON string from UTF-8; will backslash-escape the bare minimum. * Invalid UTF-8 in input will output as valid UTF-8 for each byte * Worst case: len*6 */ +__readmemsz__(2,3) size_t fmt_jsonescape(char* dest,const char* src,size_t len); +__readmemsz__(2,3) size_t fmt_base85(char* dest,const char* src,size_t len); /* These read one line from src, decode it, and write the result to