Special _vfixed gbuffer property

For snprintf style buffers which position can go beyond capacity
This commit is contained in:
Willem Toorop 2017-02-01 21:41:27 +01:00
parent f1c44dc15c
commit 2b9987014d
7 changed files with 60 additions and 24 deletions

View File

@ -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))

View File

@ -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(

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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 */

View File

@ -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) {