mirror of https://github.com/getdnsapi/getdns.git
Special _vfixed gbuffer property
For snprintf style buffers which position can go beyond capacity
This commit is contained in:
parent
f1c44dc15c
commit
2b9987014d
|
@ -1354,7 +1354,7 @@ getdns_context_create_with_extended_memory_functions(
|
|||
result->suffixes = no_suffixes;
|
||||
result->suffixes_len = sizeof(no_suffixes);
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, result->trust_anchors_spc
|
||||
gldns_buffer_init_frm_data_v(&gbuf, result->trust_anchors_spc
|
||||
, sizeof(result->trust_anchors_spc));
|
||||
|
||||
if (!_getdns_parse_ta_file(NULL, &gbuf)) {
|
||||
|
@ -2333,7 +2333,7 @@ getdns_context_set_suffix(getdns_context *context, getdns_list *value)
|
|||
context->suffixes_len = sizeof(no_suffixes);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
gldns_buffer_init_frm_data(&gbuf, buf_spc, sizeof(buf_spc));
|
||||
gldns_buffer_init_frm_data_v(&gbuf, buf_spc, sizeof(buf_spc));
|
||||
for (;;) {
|
||||
for ( i = 0
|
||||
; !(r = getdns_list_get_bindata(value, i, &bindata))
|
||||
|
|
|
@ -297,7 +297,7 @@ getdns_rr_dict2wire_scan(
|
|||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz);
|
||||
gldns_buffer_init_frm_data_v(&gbuf, *wire, *wire_sz);
|
||||
if ((r = _getdns_rr_dict2wire(rr_dict, &gbuf)))
|
||||
return r;
|
||||
|
||||
|
@ -447,7 +447,7 @@ getdns_rr_dict2str_scan(
|
|||
if (!rr_dict || !str || !*str || !str_len)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc));
|
||||
gldns_buffer_init_frm_data_v(&gbuf, buf, sizeof(buf_spc));
|
||||
r = _getdns_rr_dict2wire(rr_dict, &gbuf);
|
||||
if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
|
||||
if (!(buf = GETDNS_XMALLOC(
|
||||
|
@ -960,7 +960,7 @@ getdns_msg_dict2wire_scan(
|
|||
if (!msg_dict || !wire || !wire_sz || (!*wire && *wire_sz))
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz);
|
||||
gldns_buffer_init_frm_data_v(&gbuf, *wire, *wire_sz);
|
||||
if ((r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf)))
|
||||
return r;
|
||||
|
||||
|
@ -1036,7 +1036,7 @@ getdns_msg_dict2str_scan(
|
|||
if (!msg_dict || !str || !*str || !str_len)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc));
|
||||
gldns_buffer_init_frm_data_v(&gbuf, buf, sizeof(buf_spc));
|
||||
r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf);
|
||||
if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
|
||||
if (!(buf = GETDNS_XMALLOC(
|
||||
|
|
|
@ -1186,7 +1186,7 @@ getdns_pretty_snprint_dict(char *str, size_t size, const getdns_dict *dict)
|
|||
|
||||
if (!dict) return -1;
|
||||
|
||||
gldns_buffer_init_frm_data(&buf, str, size);
|
||||
gldns_buffer_init_frm_data_v(&buf, str, size);
|
||||
return getdns_pp_dict(&buf, 0, dict, 0) < 0
|
||||
? -1 : (int)gldns_buffer_position(&buf);
|
||||
}
|
||||
|
@ -1220,7 +1220,7 @@ getdns_pretty_snprint_list(char *str, size_t size, const getdns_list *list)
|
|||
|
||||
if (!list) return -1;
|
||||
|
||||
gldns_buffer_init_frm_data(&buf, str, size);
|
||||
gldns_buffer_init_frm_data_v(&buf, str, size);
|
||||
return getdns_pp_list(&buf, 0, list, 0, 0) < 0
|
||||
? -1 : (int)gldns_buffer_position(&buf);
|
||||
}
|
||||
|
@ -1255,7 +1255,7 @@ getdns_snprint_json_dict(
|
|||
|
||||
if (!dict) return -1;
|
||||
|
||||
gldns_buffer_init_frm_data(&buf, str, size);
|
||||
gldns_buffer_init_frm_data_v(&buf, str, size);
|
||||
return getdns_pp_dict(&buf, 0, dict, pretty ? 1 : 2) < 0
|
||||
? -1 : (int)gldns_buffer_position(&buf);
|
||||
}
|
||||
|
@ -1290,7 +1290,7 @@ getdns_snprint_json_list(
|
|||
|
||||
if (!list) return -1;
|
||||
|
||||
gldns_buffer_init_frm_data(&buf, str, size);
|
||||
gldns_buffer_init_frm_data_v(&buf, str, size);
|
||||
return getdns_pp_list(&buf, 0, list, 0, pretty ? 1 : 2) < 0
|
||||
? -1 : (int)gldns_buffer_position(&buf);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ gldns_buffer_new(size_t capacity)
|
|||
buffer->_position = 0;
|
||||
buffer->_limit = buffer->_capacity = capacity;
|
||||
buffer->_fixed = 0;
|
||||
buffer->_vfixed = 0;
|
||||
buffer->_status_err = 0;
|
||||
|
||||
gldns_buffer_invariant(buffer);
|
||||
|
@ -48,6 +49,7 @@ gldns_buffer_new_frm_data(gldns_buffer *buffer, void *data, size_t size)
|
|||
buffer->_position = 0;
|
||||
buffer->_limit = buffer->_capacity = size;
|
||||
buffer->_fixed = 0;
|
||||
buffer->_vfixed = 0;
|
||||
buffer->_data = malloc(size);
|
||||
if(!buffer->_data) {
|
||||
buffer->_status_err = 1;
|
||||
|
@ -66,6 +68,17 @@ gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size)
|
|||
buffer->_data = data;
|
||||
buffer->_capacity = buffer->_limit = size;
|
||||
buffer->_fixed = 1;
|
||||
buffer->_vfixed = 0;
|
||||
}
|
||||
|
||||
void
|
||||
gldns_buffer_init_frm_data_v(gldns_buffer *buffer, void *data, size_t size)
|
||||
{
|
||||
memset(buffer, 0, sizeof(*buffer));
|
||||
buffer->_data = data;
|
||||
buffer->_capacity = buffer->_limit = size;
|
||||
buffer->_fixed = 1;
|
||||
buffer->_vfixed = 1;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -126,7 +139,7 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...)
|
|||
if (written == -1) {
|
||||
buffer->_status_err = 1;
|
||||
return -1;
|
||||
} else if (!buffer->_fixed && (size_t) written >= remaining) {
|
||||
} else if (!buffer->_vfixed && (size_t) written >= remaining) {
|
||||
if (!gldns_buffer_reserve(buffer, (size_t) written + 1)) {
|
||||
buffer->_status_err = 1;
|
||||
return -1;
|
||||
|
|
|
@ -145,6 +145,17 @@ struct gldns_buffer
|
|||
/** If the buffer is fixed it cannot be resized */
|
||||
unsigned _fixed : 1;
|
||||
|
||||
/** If the buffer is vfixed, no more than capacity bytes willl be
|
||||
* written to _data, however the _position counter will be updated
|
||||
* with the amount that would have been written in consecutive
|
||||
* writes. This allows for a modus operandi in which a sequence is
|
||||
* written on a fixed capacity buffer (perhaps with _data on stack).
|
||||
* When everything could be written, then the _data is immediately
|
||||
* usable, if not, then a buffer could be allocated sized precisely
|
||||
* to fit the data for a second attempt.
|
||||
*/
|
||||
unsigned _vfixed : 1;
|
||||
|
||||
/** The current state of the buffer. If writing to the buffer fails
|
||||
* for any reason, this value is changed. This way, you can perform
|
||||
* multiple writes in sequence and check for success afterwards. */
|
||||
|
@ -162,9 +173,9 @@ INLINE void
|
|||
gldns_buffer_invariant(gldns_buffer *buffer)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(buffer->_position <= buffer->_limit || buffer->_fixed);
|
||||
assert(buffer->_position <= buffer->_limit || buffer->_vfixed);
|
||||
assert(buffer->_limit <= buffer->_capacity);
|
||||
assert(buffer->_data != NULL || (buffer->_capacity == 0 && buffer->_fixed));
|
||||
assert(buffer->_data != NULL || (buffer->_capacity == 0 && buffer->_vfixed));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -196,6 +207,17 @@ void gldns_buffer_new_frm_data(gldns_buffer *buffer, void *data, size_t size);
|
|||
*/
|
||||
void gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size);
|
||||
|
||||
/**
|
||||
* Setup a buffer with the data pointed to. No data copied, no memory allocs.
|
||||
* The buffer is fixed. Writes beyond size (the capacity) will update the
|
||||
* position (and not write data. This allows to determine how big the buffer
|
||||
* should have been to contain all the written data.
|
||||
* \param[in] buffer pointer to the buffer to put the data in
|
||||
* \param[in] data the data to encapsulate in the buffer
|
||||
* \param[in] size the size of the data
|
||||
*/
|
||||
void gldns_buffer_init_frm_data_v(gldns_buffer *buffer, void *data, size_t size);
|
||||
|
||||
/**
|
||||
* clears the buffer and make it ready for writing. The buffer's limit
|
||||
* is set to the capacity and the position is set to 0.
|
||||
|
@ -259,7 +281,7 @@ gldns_buffer_position(gldns_buffer *buffer)
|
|||
INLINE void
|
||||
gldns_buffer_set_position(gldns_buffer *buffer, size_t mark)
|
||||
{
|
||||
assert(mark <= buffer->_limit || buffer->_fixed);
|
||||
assert(mark <= buffer->_limit || buffer->_vfixed);
|
||||
buffer->_position = mark;
|
||||
}
|
||||
|
||||
|
@ -273,7 +295,7 @@ gldns_buffer_set_position(gldns_buffer *buffer, size_t mark)
|
|||
INLINE void
|
||||
gldns_buffer_skip(gldns_buffer *buffer, ssize_t count)
|
||||
{
|
||||
assert(buffer->_position + count <= buffer->_limit || buffer->_fixed);
|
||||
assert(buffer->_position + count <= buffer->_limit || buffer->_vfixed);
|
||||
buffer->_position += count;
|
||||
}
|
||||
|
||||
|
@ -345,7 +367,7 @@ int gldns_buffer_reserve(gldns_buffer *buffer, size_t amount);
|
|||
INLINE uint8_t *
|
||||
gldns_buffer_at(const gldns_buffer *buffer, size_t at)
|
||||
{
|
||||
assert(at <= buffer->_limit || buffer->_fixed);
|
||||
assert(at <= buffer->_limit || buffer->_vfixed);
|
||||
return buffer->_data + at;
|
||||
}
|
||||
|
||||
|
@ -395,6 +417,7 @@ INLINE size_t
|
|||
gldns_buffer_remaining_at(gldns_buffer *buffer, size_t at)
|
||||
{
|
||||
gldns_buffer_invariant(buffer);
|
||||
assert(at <= buffer->_limit || buffer->_vfixed);
|
||||
return at < buffer->_limit ? buffer->_limit - at : 0;
|
||||
}
|
||||
|
||||
|
@ -447,7 +470,7 @@ gldns_buffer_available(gldns_buffer *buffer, size_t count)
|
|||
INLINE void
|
||||
gldns_buffer_write_at(gldns_buffer *buffer, size_t at, const void *data, size_t count)
|
||||
{
|
||||
if (!buffer->_fixed)
|
||||
if (!buffer->_vfixed)
|
||||
assert(gldns_buffer_available_at(buffer, at, count));
|
||||
else if (gldns_buffer_remaining_at(buffer, at) == 0)
|
||||
return;
|
||||
|
@ -504,7 +527,7 @@ gldns_buffer_write_string(gldns_buffer *buffer, const char *str)
|
|||
INLINE void
|
||||
gldns_buffer_write_u8_at(gldns_buffer *buffer, size_t at, uint8_t data)
|
||||
{
|
||||
if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return;
|
||||
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
|
||||
assert(gldns_buffer_available_at(buffer, at, sizeof(data)));
|
||||
buffer->_data[at] = data;
|
||||
}
|
||||
|
@ -530,7 +553,7 @@ gldns_buffer_write_u8(gldns_buffer *buffer, uint8_t data)
|
|||
INLINE void
|
||||
gldns_buffer_write_u16_at(gldns_buffer *buffer, size_t at, uint16_t data)
|
||||
{
|
||||
if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return;
|
||||
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
|
||||
assert(gldns_buffer_available_at(buffer, at, sizeof(data)));
|
||||
gldns_write_uint16(buffer->_data + at, data);
|
||||
}
|
||||
|
@ -556,7 +579,7 @@ gldns_buffer_write_u16(gldns_buffer *buffer, uint16_t data)
|
|||
INLINE void
|
||||
gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data)
|
||||
{
|
||||
if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return;
|
||||
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
|
||||
assert(gldns_buffer_available_at(buffer, at, sizeof(data)));
|
||||
gldns_write_uint32(buffer->_data + at, data);
|
||||
}
|
||||
|
@ -570,7 +593,7 @@ gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data)
|
|||
INLINE void
|
||||
gldns_buffer_write_u48_at(gldns_buffer *buffer, size_t at, uint64_t data)
|
||||
{
|
||||
if (buffer->_fixed && at + 6 > buffer->_limit) return;
|
||||
if (buffer->_vfixed && at + 6 > buffer->_limit) return;
|
||||
assert(gldns_buffer_available_at(buffer, at, 6));
|
||||
gldns_write_uint48(buffer->_data + at, data);
|
||||
}
|
||||
|
|
|
@ -383,7 +383,7 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
#endif
|
||||
tsig_info = _getdns_get_tsig_info(upstream->tsig_alg);
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE);
|
||||
gldns_buffer_init_frm_data_v(&gbuf, req->response, MAXIMUM_TSIG_SPACE);
|
||||
gldns_buffer_write(&gbuf,
|
||||
upstream->tsig_dname, upstream->tsig_dname_len); /* Name */
|
||||
gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */
|
||||
|
|
|
@ -1510,7 +1510,7 @@ uint8_t *_getdns_list2wire(
|
|||
gldns_buffer gbuf;
|
||||
size_t sz;
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, buf, *buf_len);
|
||||
gldns_buffer_init_frm_data_v(&gbuf, buf, *buf_len);
|
||||
_getdns_list2wire_buf(&gbuf, l);
|
||||
|
||||
if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) {
|
||||
|
@ -1531,7 +1531,7 @@ uint8_t *_getdns_reply2wire(
|
|||
gldns_buffer gbuf;
|
||||
size_t sz;
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, buf, *buf_len);
|
||||
gldns_buffer_init_frm_data_v(&gbuf, buf, *buf_len);
|
||||
_getdns_reply2wire_buf(&gbuf, r);
|
||||
|
||||
if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) {
|
||||
|
|
Loading…
Reference in New Issue