/* The maximum size of the file we'll read in one go in read_full_file() (64M). */
#define READ_FULL_BYTES_MAX (64U*1024U*1024U - 1U)
+/* Used when a size is specified for read_full_file() with READ_FULL_FILE_UNBASE64 or _UNHEX */
+#define READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY 3
/* The maximum size of virtual files (i.e. procfs, sysfs, and other virtual "API" files) we'll read in one go
* in read_virtual_file(). Note that this limit is different (and much lower) than the READ_FULL_BYTES_MAX
size_t *ret_size) {
_cleanup_free_ char *buf = NULL;
- size_t n, n_next = 0, l;
+ size_t n, n_next = 0, l, expected_decoded_size = size;
int fd, r;
assert(f);
if (offset != UINT64_MAX && offset > LONG_MAX) /* fseek() can only deal with "long" offsets */
return -ERANGE;
+ if ((flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) != 0) {
+ if (size <= SIZE_MAX / READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY)
+ size *= READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY;
+ else
+ size = SIZE_MAX;
+ }
+
fd = fileno(f);
if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see
* fmemopen()), let's optimize our buffering */
explicit_bzero_safe(buf, n);
free_and_replace(buf, decoded);
n = l = decoded_size;
+
+ if (FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER) && l > expected_decoded_size) {
+ r = -E2BIG;
+ goto finalize;
+ }
}
if (!ret_size) {