7979#include <time.h>
8080#endif
8181
82+ /* Compile-time upper bounds for setting array sizes.
83+ * These must be >= the actual count returned by the corresponding
84+ * populate_settings_* functions, including the +MAX_USERS slack in
85+ * populate_settings_array. They are used so each populate function
86+ * can do a single exact-size malloc instead of the old
87+ * sizeof(struct)/sizeof(placeholder) over-estimate. */
88+ #define SETTINGS_BOOL_COUNT_MAX 512
89+ #define SETTINGS_INT_COUNT_MAX 64
90+ #define SETTINGS_UINT_COUNT_MAX 320
91+ #define SETTINGS_FLOAT_COUNT_MAX 128
92+ #define SETTINGS_SIZE_COUNT_MAX 8
93+ #define SETTINGS_ARRAY_COUNT_MAX (96 + MAX_USERS)
94+ #define SETTINGS_PATH_COUNT_MAX 128
95+
8296enum video_driver_enum
8397{
8498 VIDEO_GL = 0 ,
@@ -1540,7 +1554,7 @@ static struct config_array_setting *populate_settings_array(
15401554{
15411555 unsigned i = 0 ;
15421556 unsigned count = 0 ;
1543- struct config_array_setting * tmp = (struct config_array_setting * )calloc (1 , ( * size + 1 ) * sizeof (struct config_array_setting ));
1557+ struct config_array_setting * tmp = (struct config_array_setting * )calloc (SETTINGS_ARRAY_COUNT_MAX , sizeof (struct config_array_setting ));
15441558
15451559 if (!tmp )
15461560 return NULL ;
@@ -1570,13 +1584,16 @@ static struct config_array_setting *populate_settings_array(
15701584 SETTING_ARRAY ("input_android_physical_keyboard" , settings -> arrays .input_android_physical_keyboard , false, NULL , true);
15711585#endif
15721586
1573- for (i = 0 ; i < MAX_USERS ; i ++ )
15741587 {
1575- char key [32 ];
1576- size_t _len = strlcpy (key , "input_player" , sizeof (key ));
1577- _len += snprintf (key + _len , sizeof (key ) - _len , "%u" , i + 1 );
1578- strlcpy (key + _len , "_reserved_device" , sizeof (key ) - _len );
1579- SETTING_ARRAY (strdup (key ), settings -> arrays .input_reserved_devices [i ], false, NULL , true);
1588+ /* Use static storage for per-user key strings to avoid strdup/free overhead */
1589+ static char reserved_keys [MAX_USERS ][32 ];
1590+ for (i = 0 ; i < MAX_USERS ; i ++ )
1591+ {
1592+ size_t _len = strlcpy (reserved_keys [i ], "input_player" , sizeof (reserved_keys [i ]));
1593+ _len += snprintf (reserved_keys [i ] + _len , sizeof (reserved_keys [i ]) - _len , "%u" , i + 1 );
1594+ strlcpy (reserved_keys [i ] + _len , "_reserved_device" , sizeof (reserved_keys [i ]) - _len );
1595+ SETTING_ARRAY (reserved_keys [i ], settings -> arrays .input_reserved_devices [i ], false, NULL , true);
1596+ }
15801597 }
15811598
15821599#ifdef HAVE_MENU
@@ -1637,7 +1654,7 @@ static struct config_path_setting *populate_settings_path(
16371654{
16381655 unsigned count = 0 ;
16391656 recording_state_t * recording_st = recording_state_get_ptr ();
1640- struct config_path_setting * tmp = (struct config_path_setting * )calloc (1 , ( * size + 1 ) * sizeof (struct config_path_setting ));
1657+ struct config_path_setting * tmp = (struct config_path_setting * )calloc (SETTINGS_PATH_COUNT_MAX , sizeof (struct config_path_setting ));
16411658
16421659 if (!tmp )
16431660 return NULL ;
@@ -1739,10 +1756,15 @@ static struct config_path_setting *populate_settings_path(
17391756 return tmp ;
17401757}
17411758
1759+ /* ---------------------------------------------------------------------------
1760+ * SETTINGS_*_COUNT_MAX constants are defined above the populate functions.
1761+ * Compile-time check (via negative array) can be added here if needed.
1762+ * -------------------------------------------------------------------------- */
1763+
17421764static struct config_bool_setting * populate_settings_bool (
17431765 settings_t * settings , int * size )
17441766{
1745- struct config_bool_setting * tmp = (struct config_bool_setting * )calloc (1 , ( * size + 1 ) * sizeof (struct config_bool_setting ));
1767+ struct config_bool_setting * tmp = (struct config_bool_setting * )calloc (SETTINGS_BOOL_COUNT_MAX , sizeof (struct config_bool_setting ));
17461768 unsigned count = 0 ;
17471769
17481770 SETTING_BOOL ("accessibility_enable" , & settings -> bools .accessibility_enable , true, DEFAULT_ACCESSIBILITY_ENABLE , false);
@@ -2298,7 +2320,7 @@ static struct config_float_setting *populate_settings_float(
22982320 settings_t * settings , int * size )
22992321{
23002322 unsigned count = 0 ;
2301- struct config_float_setting * tmp = (struct config_float_setting * )calloc (1 , ( * size + 1 ) * sizeof (struct config_float_setting ));
2323+ struct config_float_setting * tmp = (struct config_float_setting * )calloc (SETTINGS_FLOAT_COUNT_MAX , sizeof (struct config_float_setting ));
23022324
23032325 if (!tmp )
23042326 return NULL ;
@@ -2402,7 +2424,7 @@ static struct config_uint_setting *populate_settings_uint(
24022424 settings_t * settings , int * size )
24032425{
24042426 unsigned count = 0 ;
2405- struct config_uint_setting * tmp = (struct config_uint_setting * )calloc (1 , ( * size + 1 ) * sizeof (struct config_uint_setting ));
2427+ struct config_uint_setting * tmp = (struct config_uint_setting * )calloc (SETTINGS_UINT_COUNT_MAX , sizeof (struct config_uint_setting ));
24062428
24072429 if (!tmp )
24082430 return NULL ;
@@ -2705,7 +2727,7 @@ static struct config_size_setting *populate_settings_size(
27052727 settings_t * settings , int * size )
27062728{
27072729 unsigned count = 0 ;
2708- struct config_size_setting * tmp = (struct config_size_setting * )calloc (( * size + 1 ) , sizeof (struct config_size_setting ));
2730+ struct config_size_setting * tmp = (struct config_size_setting * )calloc (SETTINGS_SIZE_COUNT_MAX , sizeof (struct config_size_setting ));
27092731
27102732 if (!tmp )
27112733 return NULL ;
@@ -2721,7 +2743,7 @@ static struct config_int_setting *populate_settings_int(
27212743 settings_t * settings , int * size )
27222744{
27232745 unsigned count = 0 ;
2724- struct config_int_setting * tmp = (struct config_int_setting * )calloc (( * size + 1 ) , sizeof (struct config_int_setting ));
2746+ struct config_int_setting * tmp = (struct config_int_setting * )calloc (SETTINGS_INT_COUNT_MAX , sizeof (struct config_int_setting ));
27252747
27262748 if (!tmp )
27272749 return NULL ;
@@ -2835,11 +2857,11 @@ void config_set_defaults(void *data)
28352857 global_t * global = (global_t * )data ;
28362858 settings_t * settings = config_st ;
28372859 recording_state_t * recording_st = recording_state_get_ptr ();
2838- int bool_settings_size = sizeof ( settings -> bools ) / sizeof ( settings -> bools . placeholder ) ;
2839- int float_settings_size = sizeof ( settings -> floats ) / sizeof ( settings -> floats . placeholder ) ;
2840- int int_settings_size = sizeof ( settings -> ints ) / sizeof ( settings -> ints . placeholder ) ;
2841- int uint_settings_size = sizeof ( settings -> uints ) / sizeof ( settings -> uints . placeholder ) ;
2842- int size_settings_size = sizeof ( settings -> sizes ) / sizeof ( settings -> sizes . placeholder ) ;
2860+ int bool_settings_size = SETTINGS_BOOL_COUNT_MAX ;
2861+ int float_settings_size = SETTINGS_FLOAT_COUNT_MAX ;
2862+ int int_settings_size = SETTINGS_INT_COUNT_MAX ;
2863+ int uint_settings_size = SETTINGS_UINT_COUNT_MAX ;
2864+ int size_settings_size = SETTINGS_SIZE_COUNT_MAX ;
28432865 const char * def_video = config_get_default_video ();
28442866 const char * def_audio = config_get_default_audio ();
28452867#ifdef HAVE_MICROPHONE
@@ -3830,13 +3852,13 @@ static bool config_load_file(global_t *global,
38303852 char * save = NULL ;
38313853 char * override_username = NULL ;
38323854 runloop_state_t * runloop_st = runloop_state_get_ptr ();
3833- int bool_settings_size = sizeof ( settings -> bools ) / sizeof ( settings -> bools . placeholder ) ;
3834- int float_settings_size = sizeof ( settings -> floats ) / sizeof ( settings -> floats . placeholder ) ;
3835- int int_settings_size = sizeof ( settings -> ints ) / sizeof ( settings -> ints . placeholder ) ;
3836- int uint_settings_size = sizeof ( settings -> uints ) / sizeof ( settings -> uints . placeholder ) ;
3837- int size_settings_size = sizeof ( settings -> sizes ) / sizeof ( settings -> sizes . placeholder ) ;
3838- int array_settings_size = sizeof ( settings -> arrays ) / sizeof ( settings -> arrays . placeholder ) ;
3839- int path_settings_size = sizeof ( settings -> paths ) / sizeof ( settings -> paths . placeholder ) ;
3855+ int bool_settings_size = SETTINGS_BOOL_COUNT_MAX ;
3856+ int float_settings_size = SETTINGS_FLOAT_COUNT_MAX ;
3857+ int int_settings_size = SETTINGS_INT_COUNT_MAX ;
3858+ int uint_settings_size = SETTINGS_UINT_COUNT_MAX ;
3859+ int size_settings_size = SETTINGS_SIZE_COUNT_MAX ;
3860+ int array_settings_size = SETTINGS_ARRAY_COUNT_MAX ;
3861+ int path_settings_size = SETTINGS_PATH_COUNT_MAX ;
38403862 struct config_bool_setting * bool_settings = NULL ;
38413863 struct config_float_setting * float_settings = NULL ;
38423864 struct config_int_setting * int_settings = NULL ;
@@ -5589,13 +5611,13 @@ bool config_save_file(const char *path)
55895611 config_file_t * conf = config_file_new_from_path_to_string (path );
55905612 settings_t * settings = config_st ;
55915613 global_t * global = global_get_ptr ();
5592- int bool_settings_size = sizeof ( settings -> bools ) / sizeof ( settings -> bools . placeholder ) ;
5593- int float_settings_size = sizeof ( settings -> floats )/ sizeof ( settings -> floats . placeholder ) ;
5594- int int_settings_size = sizeof ( settings -> ints ) / sizeof ( settings -> ints . placeholder ) ;
5595- int uint_settings_size = sizeof ( settings -> uints ) / sizeof ( settings -> uints . placeholder ) ;
5596- int size_settings_size = sizeof ( settings -> sizes ) / sizeof ( settings -> sizes . placeholder ) ;
5597- int array_settings_size = sizeof ( settings -> arrays )/ sizeof ( settings -> arrays . placeholder ) ;
5598- int path_settings_size = sizeof ( settings -> paths ) / sizeof ( settings -> paths . placeholder ) ;
5614+ int bool_settings_size = SETTINGS_BOOL_COUNT_MAX ;
5615+ int float_settings_size = SETTINGS_FLOAT_COUNT_MAX ;
5616+ int int_settings_size = SETTINGS_INT_COUNT_MAX ;
5617+ int uint_settings_size = SETTINGS_UINT_COUNT_MAX ;
5618+ int size_settings_size = SETTINGS_SIZE_COUNT_MAX ;
5619+ int array_settings_size = SETTINGS_ARRAY_COUNT_MAX ;
5620+ int path_settings_size = SETTINGS_PATH_COUNT_MAX ;
55995621
56005622 if (!conf )
56015623 conf = config_file_new_alloc ();
@@ -5865,13 +5887,13 @@ int8_t config_save_overrides(enum override_type type,
58655887 char override_directory [DIR_MAX_LENGTH ];
58665888 char override_path [PATH_MAX_LENGTH ];
58675889 settings_t * overrides = config_st ;
5868- int bool_settings_size = sizeof ( settings -> bools ) / sizeof ( settings -> bools . placeholder ) ;
5869- int float_settings_size = sizeof ( settings -> floats ) / sizeof ( settings -> floats . placeholder ) ;
5870- int int_settings_size = sizeof ( settings -> ints ) / sizeof ( settings -> ints . placeholder ) ;
5871- int uint_settings_size = sizeof ( settings -> uints ) / sizeof ( settings -> uints . placeholder ) ;
5872- int size_settings_size = sizeof ( settings -> sizes ) / sizeof ( settings -> sizes . placeholder ) ;
5873- int array_settings_size = sizeof ( settings -> arrays ) / sizeof ( settings -> arrays . placeholder ) ;
5874- int path_settings_size = sizeof ( settings -> paths ) / sizeof ( settings -> paths . placeholder ) ;
5890+ int bool_settings_size = SETTINGS_BOOL_COUNT_MAX ;
5891+ int float_settings_size = SETTINGS_FLOAT_COUNT_MAX ;
5892+ int int_settings_size = SETTINGS_INT_COUNT_MAX ;
5893+ int uint_settings_size = SETTINGS_UINT_COUNT_MAX ;
5894+ int size_settings_size = SETTINGS_SIZE_COUNT_MAX ;
5895+ int array_settings_size = SETTINGS_ARRAY_COUNT_MAX ;
5896+ int path_settings_size = SETTINGS_PATH_COUNT_MAX ;
58755897 rarch_system_info_t * sys_info = (rarch_system_info_t * )data ;
58765898 const char * core_name = sys_info ? sys_info -> info .library_name : NULL ;
58775899 const char * rarch_path_basename = path_get (RARCH_PATH_BASENAME );
@@ -5911,31 +5933,31 @@ int8_t config_save_overrides(enum override_type type,
59115933 "without-overrides" , settings );
59125934
59135935 bool_settings = populate_settings_bool (settings , & bool_settings_size );
5914- tmp_i = sizeof ( settings -> bools ) / sizeof ( settings -> bools . placeholder ) ;
5936+ tmp_i = SETTINGS_BOOL_COUNT_MAX ;
59155937 bool_overrides = populate_settings_bool (overrides , & tmp_i );
59165938
59175939 int_settings = populate_settings_int (settings , & int_settings_size );
5918- tmp_i = sizeof ( settings -> ints ) / sizeof ( settings -> ints . placeholder ) ;
5940+ tmp_i = SETTINGS_INT_COUNT_MAX ;
59195941 int_overrides = populate_settings_int (overrides , & tmp_i );
59205942
59215943 uint_settings = populate_settings_uint (settings , & uint_settings_size );
5922- tmp_i = sizeof ( settings -> uints ) / sizeof ( settings -> uints . placeholder ) ;
5944+ tmp_i = SETTINGS_UINT_COUNT_MAX ;
59235945 uint_overrides = populate_settings_uint (overrides , & tmp_i );
59245946
59255947 size_settings = populate_settings_size (settings , & size_settings_size );
5926- tmp_i = sizeof ( settings -> sizes ) / sizeof ( settings -> sizes . placeholder ) ;
5948+ tmp_i = SETTINGS_SIZE_COUNT_MAX ;
59275949 size_overrides = populate_settings_size (overrides , & tmp_i );
59285950
59295951 float_settings = populate_settings_float (settings , & float_settings_size );
5930- tmp_i = sizeof ( settings -> floats ) / sizeof ( settings -> floats . placeholder ) ;
5952+ tmp_i = SETTINGS_FLOAT_COUNT_MAX ;
59315953 float_overrides = populate_settings_float (overrides , & tmp_i );
59325954
59335955 array_settings = populate_settings_array (settings , & array_settings_size );
5934- tmp_i = sizeof ( settings -> arrays ) / sizeof ( settings -> arrays . placeholder ) ;
5956+ tmp_i = SETTINGS_ARRAY_COUNT_MAX ;
59355957 array_overrides = populate_settings_array (overrides , & tmp_i );
59365958
59375959 path_settings = populate_settings_path (settings , & path_settings_size );
5938- tmp_i = sizeof ( settings -> paths ) / sizeof ( settings -> paths . placeholder ) ;
5960+ tmp_i = SETTINGS_PATH_COUNT_MAX ;
59395961 path_overrides = populate_settings_path (overrides , & tmp_i );
59405962
59415963 if (conf -> flags & CONF_FILE_FLG_MODIFIED )
0 commit comments