summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorJean Delvare <jdelvare@suse.de>2018-08-01 09:54:55 +0200
committerJean Delvare <jdelvare@suse.de>2018-08-01 09:54:55 +0200
commitbd78a5dfd47043db08982464bcae4759c0980975 (patch)
tree957f49562a32c817bd49490a8c93d55ba0a0e6c1 /util.c
parent4cbba9a8e76ffc640eaf7dd25acbd3c1c6504669 (diff)
downloaddmidecode-git-bd78a5dfd47043db08982464bcae4759c0980975.tar.gz
dmidecode: Don't allocate more memory than needed
If the actual DMI table size is less than the announced maximum (which is allowed for 64-bit SMBIOS 3 entry points), we may allocate significantly more memory than is actually needed. If reading from /dev/mem, there's nothing we can do about that. However, is reading from sysfs or from a dump file, we can easily check the file size and compute the actual table size from it. That way we only allocate the required amount of memory. Credits to Lionel Debroux for seeding the idea when performing fuzz testing on dmidecode. Signed-off-by: Jean Delvare <jdelvare@suse.de>
Diffstat (limited to 'util.c')
-rw-r--r--util.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/util.c b/util.c
index 0aafcb1..7049817 100644
--- a/util.c
+++ b/util.c
@@ -90,16 +90,16 @@ int checksum(const u8 *buf, size_t len)
/*
* Reads all of file from given offset, up to max_len bytes.
- * A buffer of max_len bytes is allocated by this function, and
+ * A buffer of at most max_len bytes is allocated by this function, and
* needs to be freed by the caller.
* This provides a similar usage model to mem_chunk()
*
- * Returns pointer to buffer of max_len bytes, or NULL on error, and
+ * Returns a pointer to the allocated buffer, or NULL on error, and
* sets max_len to the length actually read.
- *
*/
void *read_file(off_t base, size_t *max_len, const char *filename)
{
+ struct stat statbuf;
int fd;
size_t r2 = 0;
ssize_t r;
@@ -124,6 +124,15 @@ void *read_file(off_t base, size_t *max_len, const char *filename)
goto out;
}
+ /*
+ * Check file size, don't allocate more than can be read.
+ */
+ if (fstat(fd, &statbuf) == 0)
+ {
+ if (base + (off_t)*max_len > statbuf.st_size)
+ *max_len = statbuf.st_size - base;
+ }
+
if ((p = malloc(*max_len)) == NULL)
{
perror("malloc");