mirror of
https://github.com/rkd77/elinks.git
synced 2024-09-28 03:06:20 -04:00
bug 764: Initialize the right member of union option_value
Convert the initial value of each option to void * at compile time, and make register_options() convert it back and set the appropriate member of union option_value. Previously, all initial values were left in option.value.tree and then read directly from other members of the union, failing badly on big-endian 64-bit systems.
This commit is contained in:
parent
39d03147bb
commit
9e52956a02
2
NEWS
2
NEWS
@ -12,6 +12,8 @@ To be released as 0.11.7.
|
||||
|
||||
* critical bug 1077: fix crash opening a ``javascript:'' link in a new
|
||||
tab
|
||||
* major bug 764: remove int/long/pointer type punning in union
|
||||
option_value, especially harmful on sparc64
|
||||
|
||||
ELinks 0.11.6:
|
||||
--------------
|
||||
|
@ -713,6 +713,11 @@ static struct change_hook_info change_hooks[];
|
||||
void
|
||||
init_options(void)
|
||||
{
|
||||
/* The following assignment is needed if void * and struct
|
||||
* list_head * have different representations. Otherwise,
|
||||
* the compiler should be able to optimize it out. */
|
||||
options_root.value.tree = options_root.value.compile_time_init;
|
||||
|
||||
cmdline_options = add_opt_tree_tree(&options_root, "", "",
|
||||
"cmdline", 0, "");
|
||||
register_options(cmdline_options_info, cmdline_options);
|
||||
@ -1144,26 +1149,42 @@ register_options(struct option_info info[], struct option *tree)
|
||||
delete_option(option);
|
||||
continue;
|
||||
}
|
||||
safe_strncpy(string, option->value.string, MAX_STR_LEN);
|
||||
safe_strncpy(string,
|
||||
option->value.compile_time_init,
|
||||
MAX_STR_LEN);
|
||||
option->value.string = string;
|
||||
break;
|
||||
case OPT_COLOR:
|
||||
string = option->value.string;
|
||||
string = option->value.compile_time_init;
|
||||
assert(string);
|
||||
decode_color(string, strlen(string),
|
||||
&option->value.color);
|
||||
break;
|
||||
case OPT_CODEPAGE:
|
||||
string = option->value.string;
|
||||
string = option->value.compile_time_init;
|
||||
assert(string);
|
||||
option->value.number = get_cp_index(string);
|
||||
break;
|
||||
case OPT_BOOL:
|
||||
case OPT_INT:
|
||||
case OPT_LONG:
|
||||
case OPT_LANGUAGE:
|
||||
/* Some compilers warn if we cast a
|
||||
* pointer directly to an integer with
|
||||
* a different size. */
|
||||
option->value.number = (int) (longptr_T)
|
||||
option->value.compile_time_init;
|
||||
break;
|
||||
case OPT_LONG:
|
||||
option->value.big_number = (long) (longptr_T)
|
||||
option->value.compile_time_init;
|
||||
break;
|
||||
case OPT_COMMAND:
|
||||
option->value.command =
|
||||
option->value.compile_time_init;
|
||||
break;
|
||||
case OPT_ALIAS:
|
||||
option->value.string =
|
||||
option->value.compile_time_init;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,19 @@ struct option;
|
||||
struct session;
|
||||
|
||||
union option_value {
|
||||
/* XXX: Keep first to make @options_root initialization possible. */
|
||||
/* INIT_OPTION initializes this first member at compile time.
|
||||
* In C89, only the first member of a union can be initialized.
|
||||
* So INIT_OPTION casts the default value of each option to the
|
||||
* type of this member at compile time, and register_options()
|
||||
* then casts the value back to the original type and writes it
|
||||
* to the appropriate member. The type must be a pointer type
|
||||
* because we need to store strings and (int) "foo" is not a
|
||||
* valid constant expression for an initializer in standard C.
|
||||
* We choose void * because that type has the fewest alignment
|
||||
* requirements and so is not likely to lose any bits of the
|
||||
* integers we cast to it. */
|
||||
void *compile_time_init;
|
||||
|
||||
/* The OPT_TREE list_head is allocated. */
|
||||
struct list_head *tree;
|
||||
|
||||
@ -149,7 +161,7 @@ struct option {
|
||||
};
|
||||
|
||||
#define INIT_OPTION(name, flags, type, min, max, value, desc, capt) \
|
||||
{ NULL_LIST_HEAD, INIT_OBJECT("option"), name, flags, type, min, max, { (struct list_head *) (value) }, desc, capt }
|
||||
{ NULL_LIST_HEAD, INIT_OBJECT("option"), name, flags, type, min, max, { (void *) (value) }, desc, capt }
|
||||
|
||||
extern struct option *config_options;
|
||||
extern struct option *cmdline_options;
|
||||
@ -314,13 +326,13 @@ extern void unregister_options(struct option_info info[], struct option *tree);
|
||||
{ INIT_OPTION(NULL, 0, 0, 0, 0, NULL, NULL, NULL), NULL }
|
||||
|
||||
#define INIT_OPT_BOOL(path, capt, name, flags, def, desc) \
|
||||
{ INIT_OPTION(name, flags, OPT_BOOL, 0, 1, def, DESC(desc), capt), path }
|
||||
{ INIT_OPTION(name, flags, OPT_BOOL, 0, 1, (longptr_T) def, DESC(desc), capt), path }
|
||||
|
||||
#define INIT_OPT_INT(path, capt, name, flags, min, max, def, desc) \
|
||||
{ INIT_OPTION(name, flags, OPT_INT, min, max, def, DESC(desc), capt), path }
|
||||
{ INIT_OPTION(name, flags, OPT_INT, min, max, (longptr_T) def, DESC(desc), capt), path }
|
||||
|
||||
#define INIT_OPT_LONG(path, capt, name, flags, min, max, def, desc) \
|
||||
{ INIT_OPTION(name, flags, OPT_LONG, min, max, def, DESC(desc), capt), path }
|
||||
{ INIT_OPTION(name, flags, OPT_LONG, min, max, (longptr_T) def, DESC(desc), capt), path }
|
||||
|
||||
#define INIT_OPT_STRING(path, capt, name, flags, def, desc) \
|
||||
{ INIT_OPTION(name, flags, OPT_STRING, 0, MAX_STR_LEN, def, DESC(desc), capt), path }
|
||||
|
Loading…
Reference in New Issue
Block a user