1 #include "config.h"
2 #include <assert.h>
3 #include <common/bigsize.h>
4 #include <wire/wire.h>
5 
6 #ifndef SUPERVERBOSE
7 #define SUPERVERBOSE(...)
8 #endif
9 
bigsize_len(bigsize_t v)10 size_t bigsize_len(bigsize_t v)
11 {
12 	if (v < 0xfd) {
13 		return 1;
14 	} else if (v <= 0xffff) {
15 		return 3;
16 	} else if (v <= 0xffffffff) {
17 		return 5;
18 	} else {
19 		return 9;
20 	}
21 }
22 
bigsize_put(u8 buf[BIGSIZE_MAX_LEN],bigsize_t v)23 size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN], bigsize_t v)
24 {
25 	u8 *p = buf;
26 
27 	if (v < 0xfd) {
28 		*(p++) = v;
29 	} else if (v <= 0xffff) {
30 		(*p++) = 0xfd;
31 		(*p++) = v >> 8;
32 		(*p++) = v;
33 	} else if (v <= 0xffffffff) {
34 		(*p++) = 0xfe;
35 		(*p++) = v >> 24;
36 		(*p++) = v >> 16;
37 		(*p++) = v >> 8;
38 		(*p++) = v;
39 	} else {
40 		(*p++) = 0xff;
41 		(*p++) = v >> 56;
42 		(*p++) = v >> 48;
43 		(*p++) = v >> 40;
44 		(*p++) = v >> 32;
45 		(*p++) = v >> 24;
46 		(*p++) = v >> 16;
47 		(*p++) = v >> 8;
48 		(*p++) = v;
49 	}
50 	return p - buf;
51 }
52 
bigsize_get(const u8 * p,size_t max,bigsize_t * val)53 size_t bigsize_get(const u8 *p, size_t max, bigsize_t *val)
54 {
55 	if (max < 1) {
56 		SUPERVERBOSE("EOF");
57 		return 0;
58 	}
59 
60 	switch (*p) {
61 	case 0xfd:
62 		if (max < 3) {
63 			SUPERVERBOSE("unexpected EOF");
64 			return 0;
65 		}
66 		*val = ((u64)p[1] << 8) + p[2];
67 		if (*val < 0xfd) {
68 			SUPERVERBOSE("decoded bigsize is not canonical");
69 			return 0;
70 		}
71 		return 3;
72 	case 0xfe:
73 		if (max < 5) {
74 			SUPERVERBOSE("unexpected EOF");
75 			return 0;
76 		}
77 		*val = ((u64)p[1] << 24) + ((u64)p[2] << 16)
78 			+ ((u64)p[3] << 8) + p[4];
79 		if ((*val >> 16) == 0) {
80 			SUPERVERBOSE("decoded bigsize is not canonical");
81 			return 0;
82 		}
83 		return 5;
84 	case 0xff:
85 		if (max < 9) {
86 			SUPERVERBOSE("unexpected EOF");
87 			return 0;
88 		}
89 		*val = ((u64)p[1] << 56) + ((u64)p[2] << 48)
90 			+ ((u64)p[3] << 40) + ((u64)p[4] << 32)
91 			+ ((u64)p[5] << 24) + ((u64)p[6] << 16)
92 			+ ((u64)p[7] << 8) + p[8];
93 		if ((*val >> 32) == 0) {
94 			SUPERVERBOSE("decoded bigsize is not canonical");
95 			return 0;
96 		}
97 		return 9;
98 	default:
99 		*val = *p;
100 		return 1;
101 	}
102 }
103 
fromwire_bigsize(const u8 ** cursor,size_t * max)104 bigsize_t fromwire_bigsize(const u8 **cursor, size_t *max)
105 {
106 	bigsize_t v;
107 	size_t len = bigsize_get(*cursor, *max, &v);
108 
109 	if (len == 0) {
110 		fromwire_fail(cursor, max);
111 		return 0;
112 	}
113 	assert(len <= *max);
114 	fromwire(cursor, max, NULL, len);
115 	return v;
116 }
117 
towire_bigsize(u8 ** pptr,const bigsize_t val)118 void towire_bigsize(u8 **pptr, const bigsize_t val)
119 {
120 	u8 buf[BIGSIZE_MAX_LEN];
121 	size_t len;
122 
123 	len = bigsize_put(buf, val);
124 	towire(pptr, buf, len);
125 }
126