Skip to content

Commit

Permalink
[settings] Avoid potentially large stack allocations
Browse files Browse the repository at this point in the history
Avoid potentially large stack allocations in fetchf_setting() and
storef_setting().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Jul 18, 2013
1 parent 0636451 commit 3880ebe
Showing 1 changed file with 43 additions and 26 deletions.
69 changes: 43 additions & 26 deletions src/core/settings.c
Expand Up @@ -1046,28 +1046,32 @@ int setting_cmp ( struct setting *a, struct setting *b ) {
*/
int fetchf_setting ( struct settings *settings, struct setting *setting,
char *buf, size_t len ) {
void *raw;
int raw_len;
int check_len;
int rc;
int ret;

/* Fetch raw value */
raw_len = fetch_setting_len ( settings, setting );
raw_len = fetch_setting_copy ( settings, setting, &raw );
if ( raw_len < 0 ) {
rc = raw_len;
return rc;
} else {
uint8_t raw[raw_len];

/* Fetch raw value */
check_len = fetch_setting ( settings, setting, raw,
sizeof ( raw ) );
if ( check_len < 0 )
return check_len;
assert ( check_len == raw_len );
ret = raw_len;
goto err_fetch_copy;
}

/* Format value */
return setting->type->format ( raw, sizeof ( raw ), buf, len );
/* Return error if setting does not exist */
if ( ! raw ) {
ret = -ENOENT;
goto err_exists;
}

/* Format setting */
if ( ( ret = setting->type->format ( raw, raw_len, buf, len ) ) < 0 )
goto err_format;

err_format:
free ( raw );
err_exists:
err_fetch_copy:
return ret;
}

/**
Expand All @@ -1080,6 +1084,7 @@ int fetchf_setting ( struct settings *settings, struct setting *setting,
*/
int storef_setting ( struct settings *settings, struct setting *setting,
const char *value ) {
void *raw;
int raw_len;
int check_len;
int rc;
Expand All @@ -1088,21 +1093,33 @@ int storef_setting ( struct settings *settings, struct setting *setting,
if ( ( ! value ) || ( ! value[0] ) )
return delete_setting ( settings, setting );

/* Parse formatted value */
/* Get raw value length */
raw_len = setting->type->parse ( value, NULL, 0 );
if ( raw_len < 0 ) {
rc = raw_len;
return rc;
} else {
uint8_t raw[raw_len];

/* Parse formatted value */
check_len = setting->type->parse ( value, raw, sizeof ( raw ) );
assert ( check_len == raw_len );
goto err_parse_len;
}

/* Store raw value */
return store_setting ( settings, setting, raw, sizeof ( raw ) );
/* Allocate buffer for raw value */
raw = malloc ( raw_len );
if ( ! raw ) {
rc = -ENOMEM;
goto err_alloc_raw;
}

/* Parse formatted value */
check_len = setting->type->parse ( value, raw, raw_len );
assert ( check_len == raw_len );

/* Store raw value */
if ( ( rc = store_setting ( settings, setting, raw, raw_len ) ) != 0 )
goto err_store;

err_store:
free ( raw );
err_alloc_raw:
err_parse_len:
return rc;
}

/******************************************************************************
Expand Down

0 comments on commit 3880ebe

Please sign in to comment.