vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| Good evening - I was combing through libc, and found something interesting in net/base64.c: /* XXX abort illegal in library */ #define Assert(Cond) if (!(Cond)) abort() The way that this #define is used seemed uneccesary, and, with the following test case (wherein we stuff 0xff into a uchar and see what happens), that appears to be the case: #include <ctype.h> #include <stdio.h> int main(void) { u_char input[3]; u_char output[4]; int i[4]; input[0] = input[1] = input[2] = 0xff; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = input[2] & 0x3f; i[0] = output[0]; i[1] = output[1]; i[2] = output[2]; i[3] = output[3]; printf("output[0] is %i\n", i[0]); printf("output[1] is %i\n", i[1]); printf("output[2] is %i\n", i[2]); printf("output[3] is %i\n", i[3]); input[0] = input[1] = input[2] = 0xff; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); i[0] = output[0]; i[1] = output[1]; i[2] = output[2]; printf("output[0] is %i\n", i[0]); printf("output[1] is %i\n", i[1]); printf("output[2] is %i\n", i[2]); exit(0); } Which produces an output of: output[0] is 63 output[1] is 63 output[2] is 63 output[3] is 63 output[0] is 63 output[1] is 63 output[2] is 63 It looks for all the world (to myself, at least) that the function simply _will not_ produce a value greater than 63, barring some sort of supernatural posession of the CPU (in which case, incorrect base-64 formatting is just the least of your worries). So I've made a diff (which also ansifies the functions, removes some unecessary whitespace, and KNFs the comments, as per style(9)) removing these #defines and their use. If the devs feel that the Asserts are still needed, I have another diff standing by which replaces the abort() call with a `return (-1)', and another one which just applies style(9): --- base64.c.orig Thu Aug 17 06:32:40 2006 +++ base64.c Fri Aug 18 06:29:01 2006 @@ -52,86 +52,78 @@ #include <ctype.h> #include <resolv.h> #include <stdio.h> - #include <stdlib.h> #include <string.h> -/* XXX abort illegal in library */ -#define Assert(Cond) if (!(Cond)) abort() - static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw xyz0123456789+/"; static const char Pad64 = '='; -/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) - The following encoding technique is taken from RFC 1521 by Borenstein - and Freed. It is reproduced here in a slightly edited form for - convenience. +/* + * (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + * The following encoding technique is taken from RFC 1521 by Borenstein + * and Freed. It is reproduced here in a slightly edited form for + * convenience. + * + * A 65-character subset of US-ASCII is used, enabling 6 bits to be + * represented per printable character. (The extra 65th character, "=", + * is used to signify a special processing function.) + * + * The encoding process represents 24-bit groups of input bits as output + * strings of 4 encoded characters. Proceeding from left to right, a + * 24-bit input group is formed by concatenating 3 8-bit input groups. + * These 24 bits are then treated as 4 concatenated 6-bit groups, each + * of which is translated into a single digit in the base64 alphabet. + * + * Each 6-bit group is used as an index into an array of 64 printable + * characters. The character referenced by the index is placed in the + * output string. + * + * Table 1: The Base64 Alphabet + * + * Value Encoding Value Encoding Value Encoding Value Encoding + * 0 A 17 R 34 i 51 z + * 1 B 18 S 35 j 52 0 + * 2 C 19 T 36 k 53 1 + * 3 D 20 U 37 l 54 2 + * 4 E 21 V 38 m 55 3 + * 5 F 22 W 39 n 56 4 + * 6 G 23 X 40 o 57 5 + * 7 H 24 Y 41 p 58 6 + * 8 I 25 Z 42 q 59 7 + * 9 J 26 a 43 r 60 8 + * 10 K 27 b 44 s 61 9 + * 11 L 28 c 45 t 62 + + * 12 M 29 d 46 u 63 / + * 13 N 30 e 47 v + * 14 O 31 f 48 w (pad) = + * 15 P 32 g 49 x + * 16 Q 33 h 50 y + * + * Special processing is performed if fewer than 24 bits are available + * at the end of the data being encoded. A full encoding quantum is + * always completed at the end of a quantity. When fewer than 24 input + * bits are available in an input group, zero bits are added (on the + * right) to form an integral number of 6-bit groups. Padding at the + * end of the data is performed using the '=' character. + * + * Since all base64 input is an integral number of octets, only the + * following cases can arise: + * + * (1) the final quantum of encoding input is an integral + * multiple of 24 bits; here, the final unit of encoded + * output will be an integral multiple of 4 characters + * with no "=" padding, + * (2) the final quantum of encoding input is exactly 8 bits; + * here, the final unit of encoded output will be two + * characters followed by two "=" padding characters, or + * (3) the final quantum of encoding input is exactly 16 bits; + * here, the final unit of encoded output will be three + * characters followed by one "=" padding character. + */ - A 65-character subset of US-ASCII is used, enabling 6 bits to be - represented per printable character. (The extra 65th character, "=", - is used to signify a special processing function.) - - The encoding process represents 24-bit groups of input bits as output - strings of 4 encoded characters. Proceeding from left to right, a - 24-bit input group is formed by concatenating 3 8-bit input groups. - These 24 bits are then treated as 4 concatenated 6-bit groups, each - of which is translated into a single digit in the base64 alphabet. - - Each 6-bit group is used as an index into an array of 64 printable - characters. The character referenced by the index is placed in the - output string. - - Table 1: The Base64 Alphabet - - Value Encoding Value Encoding Value Encoding Value Encoding - 0 A 17 R 34 i 51 z - 1 B 18 S 35 j 52 0 - 2 C 19 T 36 k 53 1 - 3 D 20 U 37 l 54 2 - 4 E 21 V 38 m 55 3 - 5 F 22 W 39 n 56 4 - 6 G 23 X 40 o 57 5 - 7 H 24 Y 41 p 58 6 - 8 I 25 Z 42 q 59 7 - 9 J 26 a 43 r 60 8 - 10 K 27 b 44 s 61 9 - 11 L 28 c 45 t 62 + - 12 M 29 d 46 u 63 / - 13 N 30 e 47 v - 14 O 31 f 48 w (pad) = - 15 P 32 g 49 x - 16 Q 33 h 50 y - - Special processing is performed if fewer than 24 bits are available - at the end of the data being encoded. A full encoding quantum is - always completed at the end of a quantity. When fewer than 24 input - bits are available in an input group, zero bits are added (on the - right) to form an integral number of 6-bit groups. Padding at the - end of the data is performed using the '=' character. - - Since all base64 input is an integral number of octets, only the - ------------------------------------------------- - following cases can arise: - - (1) the final quantum of encoding input is an integral - multiple of 24 bits; here, the final unit of encoded - output will be an integral multiple of 4 characters - with no "=" padding, - (2) the final quantum of encoding input is exactly 8 bits; - here, the final unit of encoded output will be two - characters followed by two "=" padding characters, or - (3) the final quantum of encoding input is exactly 16 bits; - here, the final unit of encoded output will be three - characters followed by one "=" padding character. - */ - int -b64_ntop(src, srclength, target, targsize) - u_char const *src; - size_t srclength; - char *target; - size_t targsize; +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { size_t datalength = 0; u_char input[3]; @@ -148,10 +140,6 @@ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = input[2] & 0x3f; - Assert(output[0] < 64); - Assert(output[1] < 64); - Assert(output[2] < 64); - Assert(output[3] < 64); if (datalength + 4 > targsize) return (-1); @@ -160,20 +148,17 @@ target[datalength++] = Base64[output[2]]; target[datalength++] = Base64[output[3]]; } - + /* Now we worry about padding. */ if (0 != srclength) { /* Get what's left. */ input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclength; i++) input[i] = *src++; - + output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - Assert(output[0] < 64); - Assert(output[1] < 64); - Assert(output[2] < 64); if (datalength + 4 > targsize) return (-1); @@ -191,17 +176,15 @@ return (datalength); } -/* skips all whitespace anywhere. - converts characters, four at a time, starting at (or after) - src from base - 64 numbers into three 8 bit bytes in the target area. - it returns the number of data bytes stored at the target, or -1 on error. +/* + * skips all whitespace anywhere. + * converts characters, four at a time, starting at (or after) + * src from base - 64 numbers into three 8 bit bytes in the target area. + * it returns the number of data bytes stored at the target, or -1 on error. */ int -b64_pton(src, target, targsize) - char const *src; - u_char *target; - size_t targsize; +b64_pton(char const *src, u_char *target, size_t targsize) { int tarindex, state, ch; char *pos; |