Consolidate ways to enforce bounds check on reading/writing data
We currently have bounds check logic in several places where data is read or written. A typical pattern is using one of the DECR_LEN
macros:
uint8_t *p = data;
size_t data_size = _data_size;
...
DECR_LEN(data_size, 3);
size = _gnutls_read_uint24(p);
p += 3;
While this is better than manual checks like if (data_size < 3) goto error; data_size -= 3;
, it doesn't provide a way to enforce the check in new code.
I would suggest providing a simpler (internal) API, and discouraging direct access to pointer and the length. Maybe we could reuse the existing gnutls_buffer_st
, with a couple of new constructors for statically provided data buffers:
void _gnutls_buffer_static_for_read(gnutls_buffer_st *buffer, const uint8_t *data, size_t size);
void _gnutls_buffer_static_for_write(gnutls_buffer_st *buffer, uint8_t *ptr, size_t max_size);
then the above example can be rewritten as:
gnutls_buffer_st buf;
...
_gnutls_buffer_static_for_read(&buf, data, _data_size);
...
size_t size;
ret = _gnutls_buffer_read_uint24(&buf, &size);
if (ret < 0) {
ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; /* map to any error code */
goto cleanup;
}
Writing is similarly done:
gnutls_buffer_st buf;
...
_gnutls_buffer_static_for_write(&buf, ptr, max_size);
...
ret = _gnutls_buffer_write_uint24(&buf, size);
if (ret < 0) {
ret = GNUTLS_E_SHORT_MEMORY_BUFFER; /* map to any error code */
goto cleanup;
}
Edited by Daiki Ueno