From ba77d862a3f29e2e10c359d0dd1c50b18fcdc2ff Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 9 Sep 2017 22:54:55 +0200 Subject: [PATCH] video_shader_parse.c - reduce stack usage --- gfx/video_shader_parse.c | 161 +++++++++++++++++++++++++++------------ 1 file changed, 114 insertions(+), 47 deletions(-) diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index d4d5e57d35..0f1f22710e 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -119,8 +119,6 @@ static enum gfx_wrap_type wrap_str_to_mode(const char *wrap_mode) static bool video_shader_parse_pass(config_file_t *conf, struct video_shader_pass *pass, unsigned i) { - char tmp_str[PATH_MAX_LENGTH]; - char tmp_path[PATH_MAX_LENGTH]; char shader_name[64]; char filter_name_buf[64]; char wrap_name_buf[64]; @@ -136,6 +134,9 @@ static bool video_shader_parse_pass(config_file_t *conf, char scale_type_x[64]; char scale_type_y[64]; char frame_count_mod[64]; + size_t path_size = PATH_MAX_LENGTH * sizeof(char); + char *tmp_str = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + char *tmp_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); struct gfx_fbo_scale *scale = NULL; bool tmp_bool = false; float fattr = 0.0f; @@ -150,14 +151,14 @@ static bool video_shader_parse_pass(config_file_t *conf, /* Source */ snprintf(shader_name, sizeof(shader_name), "shader%u", i); - if (!config_get_path(conf, shader_name, tmp_str, sizeof(tmp_str))) + if (!config_get_path(conf, shader_name, tmp_str, path_size)) { RARCH_ERR("Couldn't parse shader source (%s).\n", shader_name); - return false; + goto error; } - strlcpy(tmp_path, tmp_str, sizeof(tmp_path)); - path_resolve_realpath(tmp_path, sizeof(tmp_path)); + strlcpy(tmp_path, tmp_str, path_size); + path_resolve_realpath(tmp_path, path_size); if (!path_file_exists(tmp_path)) strlcpy(pass->source.path, tmp_str, sizeof(pass->source.path)); @@ -246,7 +247,7 @@ static bool video_shader_parse_pass(config_file_t *conf, break; default: RARCH_ERR("Invalid attribute.\n"); - return false; + goto error; } } @@ -267,7 +268,7 @@ static bool video_shader_parse_pass(config_file_t *conf, break; default: RARCH_ERR("Invalid attribute.\n"); - return false; + goto error; } } @@ -319,7 +320,14 @@ static bool video_shader_parse_pass(config_file_t *conf, } } + free(tmp_str); + free(tmp_path); return true; + +error: + free(tmp_str); + free(tmp_path); + return false; } /** @@ -334,15 +342,20 @@ static bool video_shader_parse_pass(config_file_t *conf, static bool video_shader_parse_textures(config_file_t *conf, struct video_shader *shader) { - char textures[1024]; + size_t path_size = PATH_MAX_LENGTH * sizeof(char); const char *id = NULL; char *save = NULL; - char tmp_path[PATH_MAX_LENGTH]; + char *textures = (char*)malloc(1024 * sizeof(char)); + char *tmp_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); textures[0] = '\0'; - if (!config_get_array(conf, "textures", textures, sizeof(textures))) + if (!config_get_array(conf, "textures", textures, 1024 * sizeof(char))) + { + free(textures); + free(tmp_path); return true; + } for (id = strtok_r(textures, ";", &save); id && shader->luts < GFX_MAX_TEXTURES; @@ -361,11 +374,12 @@ static bool video_shader_parse_textures(config_file_t *conf, sizeof(shader->lut[shader->luts].path))) { RARCH_ERR("Cannot find path to texture \"%s\" ...\n", id); - return false; + goto error; } - strlcpy(tmp_path, shader->lut[shader->luts].path, sizeof(tmp_path)); - path_resolve_realpath(tmp_path, sizeof(tmp_path)); + strlcpy(tmp_path, shader->lut[shader->luts].path, + path_size); + path_resolve_realpath(tmp_path, path_size); if (path_file_exists(tmp_path)) { @@ -394,7 +408,14 @@ static bool video_shader_parse_textures(config_file_t *conf, shader->lut[shader->luts].mipmap = false; } + free(textures); + free(tmp_path); return true; + +error: + free(textures); + free(tmp_path); + return false; } /** @@ -434,25 +455,34 @@ static struct video_shader_parameter *video_shader_parse_find_parameter( bool video_shader_resolve_current_parameters(config_file_t *conf, struct video_shader *shader) { - char parameters[4096]; + size_t param_size = 4096 * sizeof(char); + char *parameters = (char*)malloc(4096 * sizeof(char)); const char *id = NULL; char *save = NULL; if (!conf) + { + free(parameters); return false; + } parameters[0] = '\0'; /* Read in parameters which override the defaults. */ if (!config_get_array(conf, "parameters", - parameters, sizeof(parameters))) + parameters, param_size)) + { + free(parameters); return true; + } for (id = strtok_r(parameters, ";", &save); id; id = strtok_r(NULL, ";", &save)) { - struct video_shader_parameter *parameter = (struct video_shader_parameter*) - video_shader_parse_find_parameter(shader->parameters, shader->num_parameters, id); + struct video_shader_parameter *parameter = + (struct video_shader_parameter*) + video_shader_parse_find_parameter( + shader->parameters, shader->num_parameters, id); if (!parameter) { @@ -463,6 +493,8 @@ bool video_shader_resolve_current_parameters(config_file_t *conf, if (!config_get_float(conf, id, ¶meter->current)) RARCH_WARN("[CGP/GLSLP]: Parameter %s is not set in preset.\n", id); } + + free(parameters); return true; } @@ -487,28 +519,36 @@ bool video_shader_resolve_parameters(config_file_t *conf, for (i = 0; i < shader->passes; i++) { - char line[4096]; RFILE *file = NULL; + size_t line_size = 4096 * sizeof(char); + char *line = (char*)malloc(4096 * sizeof(char)); const char *path = shader->pass[i].source.path; + #ifdef HAVE_SLANG /* First try to use the more robust slang implementation to support #includes. */ /* FIXME: The check for slang can be removed if it's sufficiently tested for * GLSL/Cg as well, it should be the same implementation. */ if (!string_is_empty(path) && (string_is_equal_fast(path_get_extension(path), "slang", 5)) && slang_preprocess_parse_parameters(shader->pass[i].source.path, shader)) + { + free(line); continue; + } /* If that doesn't work, fallback to the old path. * Ideally, we'd get rid of this path sooner or later. */ #endif file = filestream_open(path, RFILE_MODE_READ_TEXT, -1); if (!file) + { + free(line); continue; + } line[0] = '\0'; while (shader->num_parameters < ARRAY_SIZE(shader->parameters) - && filestream_gets(file, line, sizeof(line))) + && filestream_gets(file, line, line_size)) { int ret = sscanf(line, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", @@ -533,6 +573,7 @@ bool video_shader_resolve_parameters(config_file_t *conf, param++; } + free(line); filestream_close(file); } @@ -554,15 +595,21 @@ bool video_shader_resolve_parameters(config_file_t *conf, static bool video_shader_parse_imports(config_file_t *conf, struct video_shader *shader) { - char imports[1024]; - char tmp_str[PATH_MAX_LENGTH]; + size_t path_size = PATH_MAX_LENGTH * sizeof(char); + char *imports = (char*)malloc(1024 * sizeof(char)); + char *tmp_str = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); const char *id = NULL; char *save = NULL; imports[0] = tmp_str[0] = '\0'; - if (!config_get_array(conf, "imports", imports, sizeof(imports))) + if (!config_get_array(conf, "imports", imports, + 1024 * sizeof(char))) + { + free(imports); + free(tmp_str); return true; + } for (id = strtok_r(imports, ";", &save); id && shader->variables < GFX_MAX_VARIABLES; @@ -595,7 +642,7 @@ static bool video_shader_parse_imports(config_file_t *conf, if (!config_get_array(conf, semantic_buf, semantic, sizeof(semantic))) { RARCH_ERR("No semantic for import variable.\n"); - return false; + goto error; } semantic_hash = djb2_calculate(semantic); @@ -622,7 +669,7 @@ static bool video_shader_parse_imports(config_file_t *conf, break; default: RARCH_ERR("Invalid semantic.\n"); - return false; + goto error; } @@ -644,7 +691,7 @@ static bool video_shader_parse_imports(config_file_t *conf, default: RARCH_ERR("Invalid input slot for import.\n"); - return false; + goto error; } } else if (config_get_hex(conf, wram_buf, &addr)) @@ -655,7 +702,7 @@ static bool video_shader_parse_imports(config_file_t *conf, else { RARCH_ERR("No address assigned to semantic.\n"); - return false; + goto error; } } @@ -665,12 +712,19 @@ static bool video_shader_parse_imports(config_file_t *conf, var->equal = equal; } - if (config_get_path(conf, "import_script", tmp_str, sizeof(tmp_str))) + if (config_get_path(conf, "import_script", tmp_str, path_size)) strlcpy(shader->script_path, tmp_str, sizeof(shader->script_path)); config_get_array(conf, "import_script_class", shader->script_class, sizeof(shader->script_class)); + free(imports); + free(tmp_str); return true; + +error: + free(imports); + free(tmp_str); + return false; } /** @@ -879,18 +933,21 @@ void video_shader_write_conf_cgp(config_file_t *conf, for (i = 0; i < shader->passes; i++) { char key[64]; - char tmp[PATH_MAX_LENGTH]; + size_t tmp_size = PATH_MAX_LENGTH * sizeof(char); + char *tmp = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); const struct video_shader_pass *pass = &shader->pass[i]; key[0] = '\0'; snprintf(key, sizeof(key), "shader%u", i); - strlcpy(tmp, pass->source.path, sizeof(tmp)); + strlcpy(tmp, pass->source.path, tmp_size); if (!path_is_absolute(tmp)) - path_resolve_realpath(tmp, sizeof(tmp)); + path_resolve_realpath(tmp, tmp_size); config_set_string(conf, key, tmp); + free(tmp); + if (pass->filter != RARCH_FILTER_UNSPEC) { snprintf(key, sizeof(key), "filter_linear%u", i); @@ -917,17 +974,18 @@ void video_shader_write_conf_cgp(config_file_t *conf, if (shader->num_parameters) { - char parameters[4096]; + size_t param_size = 4096 * sizeof(char); + char *parameters = (char*)malloc(4096 * sizeof(char)); parameters[0] = '\0'; - strlcpy(parameters, shader->parameters[0].id, sizeof(parameters)); + strlcpy(parameters, shader->parameters[0].id, param_size); for (i = 1; i < shader->num_parameters; i++) { /* O(n^2), but number of parameters is very limited. */ - strlcat(parameters, ";", sizeof(parameters)); - strlcat(parameters, shader->parameters[i].id, sizeof(parameters)); + strlcat(parameters, ";", param_size); + strlcat(parameters, shader->parameters[i].id, param_size); } config_set_string(conf, "parameters", parameters); @@ -935,24 +993,28 @@ void video_shader_write_conf_cgp(config_file_t *conf, for (i = 0; i < shader->num_parameters; i++) config_set_float(conf, shader->parameters[i].id, shader->parameters[i].current); + free(parameters); } if (shader->luts) { - char textures[4096]; + size_t tex_size = 4096 * sizeof(char); + char *textures = (char*)malloc(4096 * sizeof(char)); textures[0] = '\0'; - strlcpy(textures, shader->lut[0].id, sizeof(textures)); + strlcpy(textures, shader->lut[0].id, tex_size); for (i = 1; i < shader->luts; i++) { /* O(n^2), but number of textures is very limited. */ - strlcat(textures, ";", sizeof(textures)); - strlcat(textures, shader->lut[i].id, sizeof(textures)); + strlcat(textures, ";", tex_size); + strlcat(textures, shader->lut[i].id, tex_size); } config_set_string(conf, "textures", textures); + free(textures); + for (i = 0; i < shader->luts; i++) { char key[64]; @@ -983,22 +1045,24 @@ void video_shader_write_conf_cgp(config_file_t *conf, if (shader->variables) { - char variables[4096]; + size_t var_tmp = 4096 * sizeof(char); + char *variables = (char*)malloc(4096 * sizeof(char)); variables[0] = '\0'; - strlcpy(variables, shader->variable[0].id, sizeof(variables)); + strlcpy(variables, shader->variable[0].id, var_tmp); for (i = 1; i < shader->variables; i++) { - strlcat(variables, ";", sizeof(variables)); - strlcat(variables, shader->variable[i].id, sizeof(variables)); + strlcat(variables, ";", var_tmp); + strlcat(variables, shader->variable[i].id, var_tmp); } config_set_string(conf, "imports", variables); for (i = 0; i < shader->variables; i++) shader_write_variable(conf, &shader->variable[i]); + free(variables); } } @@ -1050,7 +1114,8 @@ void video_shader_resolve_relative(struct video_shader *shader, const char *ref_path) { unsigned i; - char tmp_path[4096]; + size_t tmp_path_size = 4096 * sizeof(char); + char *tmp_path = (char*)malloc(4096 * sizeof(char)); tmp_path[0] = '\0'; @@ -1059,23 +1124,25 @@ void video_shader_resolve_relative(struct video_shader *shader, if (!*shader->pass[i].source.path) continue; - strlcpy(tmp_path, shader->pass[i].source.path, sizeof(tmp_path)); + strlcpy(tmp_path, shader->pass[i].source.path, tmp_path_size); fill_pathname_resolve_relative(shader->pass[i].source.path, ref_path, tmp_path, sizeof(shader->pass[i].source.path)); } for (i = 0; i < shader->luts; i++) { - strlcpy(tmp_path, shader->lut[i].path, sizeof(tmp_path)); + strlcpy(tmp_path, shader->lut[i].path, tmp_path_size); fill_pathname_resolve_relative(shader->lut[i].path, ref_path, tmp_path, sizeof(shader->lut[i].path)); } if (*shader->script_path) { - strlcpy(tmp_path, shader->script_path, sizeof(tmp_path)); + strlcpy(tmp_path, shader->script_path, tmp_path_size); fill_pathname_resolve_relative(shader->script_path, ref_path, tmp_path, sizeof(shader->script_path)); } + + free(tmp_path); }