mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-19 20:49:11 +00:00
Codechange: validate that "max" value of settings fit in their storage
This is an easy mistake to make, so protect us against making such mistakes, by validating it doesn't happen.
This commit is contained in:
committed by
Patric Stout
parent
d7a70c67ba
commit
74aa934441
@@ -186,11 +186,13 @@ struct SettingsIniFile : IniLoadFile {
|
||||
};
|
||||
|
||||
OutputStore _stored_output; ///< Temporary storage of the output, until all processing is done.
|
||||
OutputStore _post_amble_output; ///< Similar to _stored_output, but for the post amble.
|
||||
|
||||
static const char *PREAMBLE_GROUP_NAME = "pre-amble"; ///< Name of the group containing the pre amble.
|
||||
static const char *PREAMBLE_GROUP_NAME = "pre-amble"; ///< Name of the group containing the pre amble.
|
||||
static const char *POSTAMBLE_GROUP_NAME = "post-amble"; ///< Name of the group containing the post amble.
|
||||
static const char *TEMPLATES_GROUP_NAME = "templates"; ///< Name of the group containing the templates.
|
||||
static const char *DEFAULTS_GROUP_NAME = "defaults"; ///< Name of the group containing default values for the template variables.
|
||||
static const char *TEMPLATES_GROUP_NAME = "templates"; ///< Name of the group containing the templates.
|
||||
static const char *VALIDATION_GROUP_NAME = "validation"; ///< Name of the group containing the validation statements.
|
||||
static const char *DEFAULTS_GROUP_NAME = "defaults"; ///< Name of the group containing default values for the template variables.
|
||||
|
||||
/**
|
||||
* Load the INI file.
|
||||
@@ -239,17 +241,84 @@ static const char *FindItemValue(const char *name, IniGroup *grp, IniGroup *defa
|
||||
return item->value->c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a single entry via a template and output this.
|
||||
* @param item The template to use for the output.
|
||||
* @param grp Group current being used for template rendering.
|
||||
* @param default_grp Default values for items not set in @grp.
|
||||
* @param output Output to use for result.
|
||||
*/
|
||||
static void DumpLine(IniItem *item, IniGroup *grp, IniGroup *default_grp, OutputStore &output)
|
||||
{
|
||||
static const int MAX_VAR_LENGTH = 64;
|
||||
|
||||
/* Prefix with #if/#ifdef/#ifndef */
|
||||
static const char * const pp_lines[] = {"if", "ifdef", "ifndef", nullptr};
|
||||
int count = 0;
|
||||
for (const char * const *name = pp_lines; *name != nullptr; name++) {
|
||||
const char *condition = FindItemValue(*name, grp, default_grp);
|
||||
if (condition != nullptr) {
|
||||
output.Add("#", 1);
|
||||
output.Add(*name);
|
||||
output.Add(" ", 1);
|
||||
output.Add(condition);
|
||||
output.Add("\n", 1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Output text of the template, except template variables of the form '$[_a-z0-9]+' which get replaced by their value. */
|
||||
const char *txt = item->value->c_str();
|
||||
while (*txt != '\0') {
|
||||
if (*txt != '$') {
|
||||
output.Add(txt, 1);
|
||||
txt++;
|
||||
continue;
|
||||
}
|
||||
txt++;
|
||||
if (*txt == '$') { // Literal $
|
||||
output.Add(txt, 1);
|
||||
txt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Read variable. */
|
||||
char variable[MAX_VAR_LENGTH];
|
||||
int i = 0;
|
||||
while (i < MAX_VAR_LENGTH - 1) {
|
||||
if (!(txt[i] == '_' || (txt[i] >= 'a' && txt[i] <= 'z') || (txt[i] >= '0' && txt[i] <= '9'))) break;
|
||||
variable[i] = txt[i];
|
||||
i++;
|
||||
}
|
||||
variable[i] = '\0';
|
||||
txt += i;
|
||||
|
||||
if (i > 0) {
|
||||
/* Find the text to output. */
|
||||
const char *valitem = FindItemValue(variable, grp, default_grp);
|
||||
if (valitem != nullptr) output.Add(valitem);
|
||||
} else {
|
||||
output.Add("$", 1);
|
||||
}
|
||||
}
|
||||
output.Add("\n", 1); // \n after the expanded template.
|
||||
while (count > 0) {
|
||||
output.Add("#endif\n");
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output all non-special sections through the template / template variable expansion system.
|
||||
* @param ifile Loaded INI data.
|
||||
*/
|
||||
static void DumpSections(IniLoadFile *ifile)
|
||||
{
|
||||
static const int MAX_VAR_LENGTH = 64;
|
||||
static const char * const special_group_names[] = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, nullptr};
|
||||
static const char * const special_group_names[] = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, VALIDATION_GROUP_NAME, nullptr};
|
||||
|
||||
IniGroup *default_grp = ifile->GetGroup(DEFAULTS_GROUP_NAME, false);
|
||||
IniGroup *templates_grp = ifile->GetGroup(TEMPLATES_GROUP_NAME, false);
|
||||
IniGroup *validation_grp = ifile->GetGroup(VALIDATION_GROUP_NAME, false);
|
||||
if (templates_grp == nullptr) return;
|
||||
|
||||
/* Output every group, using its name as template name. */
|
||||
@@ -263,61 +332,14 @@ static void DumpSections(IniLoadFile *ifile)
|
||||
fprintf(stderr, "settingsgen: Warning: Cannot find template %s\n", grp->name.c_str());
|
||||
continue;
|
||||
}
|
||||
DumpLine(template_item, grp, default_grp, _stored_output);
|
||||
|
||||
/* Prefix with #if/#ifdef/#ifndef */
|
||||
static const char * const pp_lines[] = {"if", "ifdef", "ifndef", nullptr};
|
||||
int count = 0;
|
||||
for (const char * const *name = pp_lines; *name != nullptr; name++) {
|
||||
const char *condition = FindItemValue(*name, grp, default_grp);
|
||||
if (condition != nullptr) {
|
||||
_stored_output.Add("#", 1);
|
||||
_stored_output.Add(*name);
|
||||
_stored_output.Add(" ", 1);
|
||||
_stored_output.Add(condition);
|
||||
_stored_output.Add("\n", 1);
|
||||
count++;
|
||||
if (validation_grp != nullptr) {
|
||||
IniItem *validation_item = validation_grp->GetItem(grp->name, false); // Find template value.
|
||||
if (validation_item != nullptr && validation_item->value.has_value()) {
|
||||
DumpLine(validation_item, grp, default_grp, _post_amble_output);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output text of the template, except template variables of the form '$[_a-z0-9]+' which get replaced by their value. */
|
||||
const char *txt = template_item->value->c_str();
|
||||
while (*txt != '\0') {
|
||||
if (*txt != '$') {
|
||||
_stored_output.Add(txt, 1);
|
||||
txt++;
|
||||
continue;
|
||||
}
|
||||
txt++;
|
||||
if (*txt == '$') { // Literal $
|
||||
_stored_output.Add(txt, 1);
|
||||
txt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Read variable. */
|
||||
char variable[MAX_VAR_LENGTH];
|
||||
int i = 0;
|
||||
while (i < MAX_VAR_LENGTH - 1) {
|
||||
if (!(txt[i] == '_' || (txt[i] >= 'a' && txt[i] <= 'z') || (txt[i] >= '0' && txt[i] <= '9'))) break;
|
||||
variable[i] = txt[i];
|
||||
i++;
|
||||
}
|
||||
variable[i] = '\0';
|
||||
txt += i;
|
||||
|
||||
if (i > 0) {
|
||||
/* Find the text to output. */
|
||||
const char *valitem = FindItemValue(variable, grp, default_grp);
|
||||
if (valitem != nullptr) _stored_output.Add(valitem);
|
||||
} else {
|
||||
_stored_output.Add("$", 1);
|
||||
}
|
||||
}
|
||||
_stored_output.Add("\n", 1); // \n after the expanded template.
|
||||
while (count > 0) {
|
||||
_stored_output.Add("#endif\n");
|
||||
count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,6 +498,7 @@ int CDECL main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
_stored_output.Clear();
|
||||
_post_amble_output.Clear();
|
||||
|
||||
for (int i = 0; i < mgo.numleft; i++) ProcessIniFile(mgo.argv[i]);
|
||||
|
||||
@@ -483,6 +506,7 @@ int CDECL main(int argc, char *argv[])
|
||||
if (output_file == nullptr) {
|
||||
CopyFile(before_file, stdout);
|
||||
_stored_output.Write(stdout);
|
||||
_post_amble_output.Write(stdout);
|
||||
CopyFile(after_file, stdout);
|
||||
} else {
|
||||
static const char * const tmp_output = "tmp2.xxx";
|
||||
@@ -494,6 +518,7 @@ int CDECL main(int argc, char *argv[])
|
||||
}
|
||||
CopyFile(before_file, fp);
|
||||
_stored_output.Write(fp);
|
||||
_post_amble_output.Write(fp);
|
||||
CopyFile(after_file, fp);
|
||||
fclose(fp);
|
||||
|
||||
|
Reference in New Issue
Block a user