]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/sldns/sbuffer.c
Fix multiple vulnerabilities in unbound.
[FreeBSD/FreeBSD.git] / contrib / unbound / sldns / sbuffer.c
1 /*
2  * buffer.c -- generic memory buffer .
3  *
4  * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 /**
10  * \file
11  *
12  * This file contains the definition of sldns_buffer, and functions to manipulate those.
13  */
14 #include "config.h"
15 #include "sldns/sbuffer.h"
16 #include <stdarg.h>
17
18 sldns_buffer *
19 sldns_buffer_new(size_t capacity)
20 {
21         sldns_buffer *buffer = (sldns_buffer*)malloc(sizeof(sldns_buffer));
22
23         if (!buffer) {
24                 return NULL;
25         }
26         
27         buffer->_data = (uint8_t *) malloc(capacity);
28         if (!buffer->_data) {
29                 free(buffer);
30                 return NULL;
31         }
32         
33         buffer->_position = 0;
34         buffer->_limit = buffer->_capacity = capacity;
35         buffer->_fixed = 0;
36         buffer->_status_err = 0;
37         
38         sldns_buffer_invariant(buffer);
39         
40         return buffer;
41 }
42
43 void
44 sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
45 {
46         assert(data != NULL);
47
48         buffer->_position = 0; 
49         buffer->_limit = buffer->_capacity = size;
50         buffer->_fixed = 0;
51         if (!buffer->_fixed && buffer->_data)
52                 free(buffer->_data);
53         buffer->_data = malloc(size);
54         if(!buffer->_data) {
55                 buffer->_status_err = 1;
56                 return;
57         }
58         memcpy(buffer->_data, data, size);
59         buffer->_status_err = 0;
60         
61         sldns_buffer_invariant(buffer);
62 }
63
64 void
65 sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
66 {
67         memset(buffer, 0, sizeof(*buffer));
68         buffer->_data = data;
69         buffer->_capacity = buffer->_limit = size;
70         buffer->_fixed = 1;
71 }
72
73 int
74 sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
75 {
76         void *data;
77         
78         sldns_buffer_invariant(buffer);
79         assert(buffer->_position <= capacity && !buffer->_fixed);
80
81         data = (uint8_t *) realloc(buffer->_data, capacity);
82         if (!data) {
83                 buffer->_status_err = 1;
84                 return 0;
85         } else {
86                 buffer->_data = data;
87                 buffer->_limit = buffer->_capacity = capacity;
88                 return 1;
89         }
90 }
91
92 int
93 sldns_buffer_reserve(sldns_buffer *buffer, size_t amount)
94 {
95         sldns_buffer_invariant(buffer);
96         assert(!buffer->_fixed);
97         if (buffer->_capacity < buffer->_position + amount) {
98                 size_t new_capacity = buffer->_capacity * 3 / 2;
99
100                 if (new_capacity < buffer->_position + amount) {
101                         new_capacity = buffer->_position + amount;
102                 }
103                 if (!sldns_buffer_set_capacity(buffer, new_capacity)) {
104                         buffer->_status_err = 1;
105                         return 0;
106                 }
107         }
108         buffer->_limit = buffer->_capacity;
109         return 1;
110 }
111
112 int
113 sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
114 {
115         va_list args;
116         int written = 0;
117         size_t remaining;
118         
119         if (sldns_buffer_status_ok(buffer)) {
120                 sldns_buffer_invariant(buffer);
121                 assert(buffer->_limit == buffer->_capacity);
122
123                 remaining = sldns_buffer_remaining(buffer);
124                 va_start(args, format);
125                 written = vsnprintf((char *) sldns_buffer_current(buffer), remaining,
126                                     format, args);
127                 va_end(args);
128                 if (written == -1) {
129                         buffer->_status_err = 1;
130                         return -1;
131                 }
132                 buffer->_position += written;
133         }
134         return written;
135 }
136
137 void
138 sldns_buffer_free(sldns_buffer *buffer)
139 {
140         if (!buffer) {
141                 return;
142         }
143
144         if (!buffer->_fixed)
145                 free(buffer->_data);
146
147         free(buffer);
148 }
149
150 void 
151 sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from)
152 {
153         size_t tocopy = sldns_buffer_limit(from);
154
155         if(tocopy > sldns_buffer_capacity(result))
156                 tocopy = sldns_buffer_capacity(result);
157         sldns_buffer_clear(result);
158         sldns_buffer_write(result, sldns_buffer_begin(from), tocopy);
159         sldns_buffer_flip(result);
160 }