olm/fuzzers/include/fuzzing.hh
Denis Kasak 8d1cfd207a Fix a fuzzing harness double free when input is of size 0.
Consider the case when the input is size 0. In this case, `count` and
`buffer_pos` will be 0 as well. The `realloc` call in the `count == 0`
branch will then effectively become a free.

However, `realloc` can sometimes return `NULL` when a 0 is passed for
the size. The current code assumes that this only happens on a memory
allocation error and breaks out of the loop. This then becomes a double
free because the buffer is freed a second time, causing an abort.

The intent of the `realloc` is probably to downsize the buffer to fit
the data exactly in order to make incorrect memory access more obvious.
This commit skips this downsizing if the size of the input data is 0.
2021-05-10 21:04:44 +00:00

84 lines
2 KiB
C++

#include "olm/olm.hh"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
ssize_t read_file(
int fd,
uint8_t **buffer
) {
size_t buffer_size = 4096;
uint8_t * current_buffer = (uint8_t *) malloc(buffer_size);
if (current_buffer == NULL) return -1;
size_t buffer_pos = 0;
while (1) {
ssize_t count = read(
fd, current_buffer + buffer_pos, buffer_size - buffer_pos
);
if (count < 0) break;
if (count == 0) {
if (buffer_pos != 0) {
current_buffer = (uint8_t *) realloc(current_buffer, buffer_pos);
if (current_buffer == NULL) break;
}
*buffer = current_buffer;
return buffer_pos;
}
buffer_pos += count;
if (buffer_pos == buffer_size) {
buffer_size *= 2;
uint8_t * new_buffer = (uint8_t *) realloc(current_buffer, buffer_size);
if (new_buffer == NULL) break;
current_buffer = new_buffer;
}
}
free(current_buffer);
return -1;
}
template<typename T>
T check_errno(
const char * message,
T value
) {
if (value == T(-1)) {
perror(message);
exit(1);
}
return value;
}
template<typename T, typename F>
size_t check_error(
F f,
T * object,
const char * message,
size_t value
) {
if (value == olm_error()) {
const char * olm_message = f(object);
ssize_t ignored;
ignored = write(STDERR_FILENO, message, strlen(message));
ignored = write(STDERR_FILENO, ": ", 2);
ignored = write(STDERR_FILENO, olm_message, strlen(olm_message));
ignored = write(STDERR_FILENO, "\n", 1);
exit(2);
return ignored;
}
return value;
}
size_t check_session(
OlmSession * session,
const char * message,
size_t value
) {
return check_error(olm_session_last_error, session, message, value);
}