float: fix buffer overrun
[nasm.git] / saa.c
blob5fab4bbd0a673a3ebd91b28011162f6c3542d599
1 #include "compiler.h"
2 #include "nasmlib.h"
3 #include "saa.h"
5 /* Aggregate SAA components smaller than this */
6 #define SAA_BLKSHIFT 16
7 #define SAA_BLKLEN ((size_t)1 << SAA_BLKSHIFT)
9 struct SAA *saa_init(size_t elem_len)
11 struct SAA *s;
12 char *data;
14 s = nasm_zalloc(sizeof(struct SAA));
16 if (elem_len >= SAA_BLKLEN)
17 s->blk_len = elem_len;
18 else
19 s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len);
21 s->elem_len = elem_len;
22 s->length = s->blk_len;
23 data = nasm_malloc(s->blk_len);
24 s->nblkptrs = s->nblks = 1;
25 s->blk_ptrs = nasm_malloc(sizeof(char *));
26 s->blk_ptrs[0] = data;
27 s->wblk = s->rblk = &s->blk_ptrs[0];
29 return s;
32 void saa_free(struct SAA *s)
34 char **p;
35 size_t n;
37 for (p = s->blk_ptrs, n = s->nblks; n; p++, n--)
38 nasm_free(*p);
40 nasm_free(s->blk_ptrs);
41 nasm_free(s);
44 /* Add one allocation block to an SAA */
45 static void saa_extend(struct SAA *s)
47 size_t blkn = s->nblks++;
49 if (blkn >= s->nblkptrs) {
50 size_t rindex = s->rblk - s->blk_ptrs;
51 size_t windex = s->wblk - s->blk_ptrs;
53 s->nblkptrs <<= 1;
54 s->blk_ptrs =
55 nasm_realloc(s->blk_ptrs, s->nblkptrs * sizeof(char *));
57 s->rblk = s->blk_ptrs + rindex;
58 s->wblk = s->blk_ptrs + windex;
61 s->blk_ptrs[blkn] = nasm_malloc(s->blk_len);
62 s->length += s->blk_len;
65 void *saa_wstruct(struct SAA *s)
67 void *p;
69 if (s->wpos % s->elem_len)
70 nasm_malloc_error(ERR_PANIC | ERR_NOFILE,
71 "misaligned wpos in saa_wstruct");
73 if (s->wpos + s->elem_len > s->blk_len) {
74 if (s->wpos != s->blk_len)
75 nasm_malloc_error(ERR_PANIC | ERR_NOFILE,
76 "unfilled block in saa_wstruct");
78 if (s->wptr + s->elem_len > s->length)
79 saa_extend(s);
80 s->wblk++;
81 s->wpos = 0;
84 p = *s->wblk + s->wpos;
85 s->wpos += s->elem_len;
86 s->wptr += s->elem_len;
88 if (s->wptr > s->datalen)
89 s->datalen = s->wptr;
91 return p;
94 void saa_wbytes(struct SAA *s, const void *data, size_t len)
96 const char *d = data;
98 while (len) {
99 size_t l = s->blk_len - s->wpos;
100 if (l > len)
101 l = len;
102 if (l) {
103 if (d) {
104 memcpy(*s->wblk + s->wpos, d, l);
105 d += l;
106 } else
107 memset(*s->wblk + s->wpos, 0, l);
108 s->wpos += l;
109 s->wptr += l;
110 len -= l;
112 if (s->datalen < s->wptr)
113 s->datalen = s->wptr;
115 if (len) {
116 if (s->wptr >= s->length)
117 saa_extend(s);
118 s->wblk++;
119 s->wpos = 0;
124 void saa_rewind(struct SAA *s)
126 s->rblk = s->blk_ptrs;
127 s->rpos = s->rptr = 0;
130 void *saa_rstruct(struct SAA *s)
132 void *p;
134 if (s->rptr + s->elem_len > s->datalen)
135 return NULL;
137 if (s->rpos % s->elem_len)
138 nasm_malloc_error(ERR_PANIC | ERR_NOFILE,
139 "misaligned rpos in saa_rstruct");
141 if (s->rpos + s->elem_len > s->blk_len) {
142 s->rblk++;
143 s->rpos = 0;
146 p = *s->rblk + s->rpos;
147 s->rpos += s->elem_len;
148 s->rptr += s->elem_len;
150 return p;
153 const void *saa_rbytes(struct SAA *s, size_t * lenp)
155 const void *p;
156 size_t len;
158 if (s->rptr >= s->datalen) {
159 *lenp = 0;
160 return NULL;
163 if (s->rpos >= s->blk_len) {
164 s->rblk++;
165 s->rpos = 0;
168 len = *lenp;
169 if (len > s->datalen - s->rptr)
170 len = s->datalen - s->rptr;
171 if (len > s->blk_len - s->rpos)
172 len = s->blk_len - s->rpos;
174 *lenp = len;
175 p = *s->rblk + s->rpos;
177 s->rpos += len;
178 s->rptr += len;
180 return p;
183 void saa_rnbytes(struct SAA *s, void *data, size_t len)
185 char *d = data;
187 if (s->rptr + len > s->datalen) {
188 nasm_malloc_error(ERR_PANIC | ERR_NOFILE,
189 "overrun in saa_rnbytes");
190 return;
193 while (len) {
194 size_t l;
195 const void *p;
197 l = len;
198 p = saa_rbytes(s, &l);
200 memcpy(d, p, l);
201 d += l;
202 len -= l;
206 /* Same as saa_rnbytes, except position the counter first */
207 void saa_fread(struct SAA *s, size_t posn, void *data, size_t len)
209 size_t ix;
211 if (posn + len > s->datalen) {
212 nasm_malloc_error(ERR_PANIC | ERR_NOFILE, "overrun in saa_fread");
213 return;
216 if (likely(s->blk_len == SAA_BLKLEN)) {
217 ix = posn >> SAA_BLKSHIFT;
218 s->rpos = posn & (SAA_BLKLEN - 1);
219 } else {
220 ix = posn / s->blk_len;
221 s->rpos = posn % s->blk_len;
223 s->rptr = posn;
224 s->rblk = &s->blk_ptrs[ix];
226 saa_rnbytes(s, data, len);
229 /* Same as saa_wbytes, except position the counter first */
230 void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len)
232 size_t ix;
234 if (posn > s->datalen) {
235 /* Seek beyond the end of the existing array not supported */
236 nasm_malloc_error(ERR_PANIC | ERR_NOFILE, "overrun in saa_fwrite");
237 return;
240 if (likely(s->blk_len == SAA_BLKLEN)) {
241 ix = posn >> SAA_BLKSHIFT;
242 s->wpos = posn & (SAA_BLKLEN - 1);
243 } else {
244 ix = posn / s->blk_len;
245 s->wpos = posn % s->blk_len;
247 s->wptr = posn;
248 s->wblk = &s->blk_ptrs[ix];
250 if (!s->wpos) {
251 s->wpos = s->blk_len;
252 s->wblk--;
255 saa_wbytes(s, data, len);
258 void saa_fpwrite(struct SAA *s, FILE * fp)
260 const char *data;
261 size_t len;
263 saa_rewind(s);
264 while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL)
265 fwrite(data, 1, len, fp);
268 void saa_write8(struct SAA *s, uint8_t v)
270 saa_wbytes(s, &v, 1);
273 #ifdef WORDS_LITTEENDIAN
275 void saa_write16(struct SAA *s, uint16_t v)
277 saa_wbytes(s, &v, 2);
280 void saa_write32(struct SAA *s, uint32_t v)
282 saa_wbytes(s, &v, 4);
285 void saa_write64(struct SAA *s, uint64_t v)
287 saa_wbytes(s, &v, 8);
290 #else /* not WORDS_LITTLEENDIAN */
292 void saa_write16(struct SAA *s, uint16_t v)
294 uint8_t b[2];
296 b[0] = v;
297 b[1] = v >> 8;
298 saa_wbytes(s, b, 2);
301 void saa_write32(struct SAA *s, uint32_t v)
303 uint8_t b[4];
305 b[0] = v;
306 b[1] = v >> 8;
307 b[2] = v >> 16;
308 b[3] = v >> 24;
309 saa_wbytes(s, b, 4);
312 void saa_write64(struct SAA *s, uint64_t v)
314 uint8_t b[8];
316 b[0] = v;
317 b[1] = v >> 8;
318 b[2] = v >> 16;
319 b[3] = v >> 24;
320 b[4] = v >> 32;
321 b[5] = v >> 40;
322 b[6] = v >> 48;
323 b[7] = v >> 56;
324 saa_wbytes(s, b, 8);
327 #endif /* WORDS_LITTLEENDIAN */
329 /* write unsigned LEB128 value to SAA */
330 void saa_wleb128u(struct SAA *psaa, int value)
332 char temp[64], *ptemp;
333 uint8_t byte;
334 int len;
336 ptemp = temp;
337 len = 0;
338 do {
339 byte = value & 127;
340 value >>= 7;
341 if (value != 0) /* more bytes to come */
342 byte |= 0x80;
343 *ptemp = byte;
344 ptemp++;
345 len++;
346 } while (value != 0);
347 saa_wbytes(psaa, temp, len);
350 /* write signed LEB128 value to SAA */
351 void saa_wleb128s(struct SAA *psaa, int value)
353 char temp[64], *ptemp;
354 uint8_t byte;
355 bool more, negative;
356 int size, len;
358 ptemp = temp;
359 more = 1;
360 negative = (value < 0);
361 size = sizeof(int) * 8;
362 len = 0;
363 while (more) {
364 byte = value & 0x7f;
365 value >>= 7;
366 if (negative)
367 /* sign extend */
368 value |= -(1 << (size - 7));
369 /* sign bit of byte is second high order bit (0x40) */
370 if ((value == 0 && !(byte & 0x40)) ||
371 ((value == -1) && (byte & 0x40)))
372 more = 0;
373 else
374 byte |= 0x80;
375 *ptemp = byte;
376 ptemp++;
377 len++;
379 saa_wbytes(psaa, temp, len);