Browse Source

[settings] Avoid potentially large stack allocations

Avoid potentially large stack allocations in fetchf_setting() and
storef_setting().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
3880ebeb18
1 changed files with 43 additions and 26 deletions
  1. 43
    26
      src/core/settings.c

+ 43
- 26
src/core/settings.c View File

1046
  */
1046
  */
1047
 int fetchf_setting ( struct settings *settings, struct setting *setting,
1047
 int fetchf_setting ( struct settings *settings, struct setting *setting,
1048
 		     char *buf, size_t len ) {
1048
 		     char *buf, size_t len ) {
1049
+	void *raw;
1049
 	int raw_len;
1050
 	int raw_len;
1050
-	int check_len;
1051
-	int rc;
1051
+	int ret;
1052
 
1052
 
1053
 	/* Fetch raw value */
1053
 	/* Fetch raw value */
1054
-	raw_len = fetch_setting_len ( settings, setting );
1054
+	raw_len = fetch_setting_copy ( settings, setting, &raw );
1055
 	if ( raw_len < 0 ) {
1055
 	if ( raw_len < 0 ) {
1056
-		rc = raw_len;
1057
-		return rc;
1058
-	} else {
1059
-		uint8_t raw[raw_len];
1060
-
1061
-		/* Fetch raw value */
1062
-		check_len = fetch_setting ( settings, setting, raw,
1063
-					    sizeof ( raw ) );
1064
-		if ( check_len < 0 )
1065
-			return check_len;
1066
-		assert ( check_len == raw_len );
1056
+		ret = raw_len;
1057
+		goto err_fetch_copy;
1058
+	}
1067
 
1059
 
1068
-		/* Format value */
1069
-		return setting->type->format ( raw, sizeof ( raw ), buf, len );
1060
+	/* Return error if setting does not exist */
1061
+	if ( ! raw ) {
1062
+		ret = -ENOENT;
1063
+		goto err_exists;
1070
 	}
1064
 	}
1065
+
1066
+	/* Format setting */
1067
+	if ( ( ret = setting->type->format ( raw, raw_len, buf, len ) ) < 0 )
1068
+		goto err_format;
1069
+
1070
+ err_format:
1071
+	free ( raw );
1072
+ err_exists:
1073
+ err_fetch_copy:
1074
+	return ret;
1071
 }
1075
 }
1072
 
1076
 
1073
 /**
1077
 /**
1080
  */
1084
  */
1081
 int storef_setting ( struct settings *settings, struct setting *setting,
1085
 int storef_setting ( struct settings *settings, struct setting *setting,
1082
 		     const char *value ) {
1086
 		     const char *value ) {
1087
+	void *raw;
1083
 	int raw_len;
1088
 	int raw_len;
1084
 	int check_len;
1089
 	int check_len;
1085
 	int rc;
1090
 	int rc;
1088
 	if ( ( ! value ) || ( ! value[0] ) )
1093
 	if ( ( ! value ) || ( ! value[0] ) )
1089
 		return delete_setting ( settings, setting );
1094
 		return delete_setting ( settings, setting );
1090
 
1095
 
1091
-	/* Parse formatted value */
1096
+	/* Get raw value length */
1092
 	raw_len = setting->type->parse ( value, NULL, 0 );
1097
 	raw_len = setting->type->parse ( value, NULL, 0 );
1093
 	if ( raw_len < 0 ) {
1098
 	if ( raw_len < 0 ) {
1094
 		rc = raw_len;
1099
 		rc = raw_len;
1095
-		return rc;
1096
-	} else {
1097
-		uint8_t raw[raw_len];
1098
-
1099
-		/* Parse formatted value */
1100
-		check_len = setting->type->parse ( value, raw, sizeof ( raw ) );
1101
-		assert ( check_len == raw_len );
1100
+		goto err_parse_len;
1101
+	}
1102
 
1102
 
1103
-		/* Store raw value */
1104
-		return store_setting ( settings, setting, raw, sizeof ( raw ) );
1103
+	/* Allocate buffer for raw value */
1104
+	raw = malloc ( raw_len );
1105
+	if ( ! raw ) {
1106
+		rc = -ENOMEM;
1107
+		goto err_alloc_raw;
1105
 	}
1108
 	}
1109
+
1110
+	/* Parse formatted value */
1111
+	check_len = setting->type->parse ( value, raw, raw_len );
1112
+	assert ( check_len == raw_len );
1113
+
1114
+	/* Store raw value */
1115
+	if ( ( rc = store_setting ( settings, setting, raw, raw_len ) ) != 0 )
1116
+		goto err_store;
1117
+
1118
+ err_store:
1119
+	free ( raw );
1120
+ err_alloc_raw:
1121
+ err_parse_len:
1122
+	return rc;
1106
 }
1123
 }
1107
 
1124
 
1108
 /******************************************************************************
1125
 /******************************************************************************

Loading…
Cancel
Save