• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 static inline int
dec_loop_generic_32_inner(const uint8_t ** s,uint8_t ** o,size_t * rounds)2 dec_loop_generic_32_inner (const uint8_t **s, uint8_t **o, size_t *rounds)
3 {
4 	const uint32_t str
5 		= base64_table_dec_32bit_d0[(*s)[0]]
6 		| base64_table_dec_32bit_d1[(*s)[1]]
7 		| base64_table_dec_32bit_d2[(*s)[2]]
8 		| base64_table_dec_32bit_d3[(*s)[3]];
9 
10 #if BASE64_LITTLE_ENDIAN
11 
12 	// LUTs for little-endian set MSB in case of invalid character:
13 	if (str & UINT32_C(0x80000000)) {
14 		return 0;
15 	}
16 #else
17 	// LUTs for big-endian set LSB in case of invalid character:
18 	if (str & UINT32_C(1)) {
19 		return 0;
20 	}
21 #endif
22 	// Store the output:
23 	memcpy(*o, &str, sizeof (str));
24 
25 	*s += 4;
26 	*o += 3;
27 	*rounds -= 1;
28 
29 	return 1;
30 }
31 
32 static inline void
dec_loop_generic_32(const uint8_t ** s,size_t * slen,uint8_t ** o,size_t * olen)33 dec_loop_generic_32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
34 {
35 	if (*slen < 8) {
36 		return;
37 	}
38 
39 	// Process blocks of 4 bytes per round. Because one extra zero byte is
40 	// written after the output, ensure that there will be at least 4 bytes
41 	// of input data left to cover the gap. (Two data bytes and up to two
42 	// end-of-string markers.)
43 	size_t rounds = (*slen - 4) / 4;
44 
45 	*slen -= rounds * 4;	// 4 bytes consumed per round
46 	*olen += rounds * 3;	// 3 bytes produced per round
47 
48 	do {
49 		if (rounds >= 8) {
50 			if (dec_loop_generic_32_inner(s, o, &rounds) &&
51 			    dec_loop_generic_32_inner(s, o, &rounds) &&
52 			    dec_loop_generic_32_inner(s, o, &rounds) &&
53 			    dec_loop_generic_32_inner(s, o, &rounds) &&
54 			    dec_loop_generic_32_inner(s, o, &rounds) &&
55 			    dec_loop_generic_32_inner(s, o, &rounds) &&
56 			    dec_loop_generic_32_inner(s, o, &rounds) &&
57 			    dec_loop_generic_32_inner(s, o, &rounds)) {
58 				continue;
59 			}
60 			break;
61 		}
62 		if (rounds >= 4) {
63 			if (dec_loop_generic_32_inner(s, o, &rounds) &&
64 			    dec_loop_generic_32_inner(s, o, &rounds) &&
65 			    dec_loop_generic_32_inner(s, o, &rounds) &&
66 			    dec_loop_generic_32_inner(s, o, &rounds)) {
67 				continue;
68 			}
69 			break;
70 		}
71 		if (rounds >= 2) {
72 			if (dec_loop_generic_32_inner(s, o, &rounds) &&
73 			    dec_loop_generic_32_inner(s, o, &rounds)) {
74 				continue;
75 			}
76 			break;
77 		}
78 		dec_loop_generic_32_inner(s, o, &rounds);
79 		break;
80 
81 	} while (rounds > 0);
82 
83 	// Adjust for any rounds that were skipped:
84 	*slen += rounds * 4;
85 	*olen -= rounds * 3;
86 }
87