This function is only used by gfxmenu. Moving it there is unfortunately a bit messy, but it frees up a fairly substantial amount (in relative terms) of precious core image space on i386-pc.
DOWN: obj/i386-pc/grub-core/kernel.img (31740 > 31528) - change: -212 UP: obj/i386-pc/grub-core/gfxmenu.mod (39816 < 40216) - change: 400 DOWN: i386-pc core image (biosdisk ext2 part_msdos) (27453 > 27351) - change: -102 DOWN: i386-pc core image (biosdisk ext2 part_msdos diskfilter mdraid09) (32367 > 32259) - change: -108 Signed-off-by: Colin Watson <cjwat...@debian.org> --- grub-core/gfxmenu/gui_string_util.c | 36 +++++++++++ grub-core/kern/misc.c | 99 +++++++---------------------- include/grub/gui_string_util.h | 16 +++++ include/grub/misc.h | 41 +++++++----- 4 files changed, 100 insertions(+), 92 deletions(-) diff --git a/grub-core/gfxmenu/gui_string_util.c b/grub-core/gfxmenu/gui_string_util.c index ba1e1eab3..119802326 100644 --- a/grub-core/gfxmenu/gui_string_util.c +++ b/grub-core/gfxmenu/gui_string_util.c @@ -204,3 +204,39 @@ grub_get_dirname (const char *file_path) return grub_new_substring (file_path, 0, last_slash + 1); } + +grub_err_t +grub_printf_fmt_check (const char *fmt, const char *fmt_expected) +{ + struct grub_printf_args args_expected, args_fmt; + grub_err_t ret; + grub_size_t n; + + if (fmt == NULL || fmt_expected == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid format"); + + ret = grub_parse_printf_arg_fmt (fmt_expected, &args_expected, 1, + GRUB_SIZE_MAX); + if (ret != GRUB_ERR_NONE) + return ret; + + /* Limit parsing to the number of expected arguments. */ + ret = grub_parse_printf_arg_fmt (fmt, &args_fmt, 1, args_expected.count); + if (ret != GRUB_ERR_NONE) + { + grub_free_printf_args (&args_expected); + return ret; + } + + for (n = 0; n < args_fmt.count; n++) + if (args_fmt.ptr[n].type != args_expected.ptr[n].type) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments types do not match"); + break; + } + + grub_free_printf_args (&args_expected); + grub_free_printf_args (&args_fmt); + + return ret; +} diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 3af336ee2..9d84f0704 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -25,36 +25,15 @@ #include <grub/env.h> #include <grub/i18n.h> -union printf_arg -{ - /* Yes, type is also part of union as the moment we fill the value - we don't need to store its type anymore (when we'll need it, we'll - have format spec again. So save some space. */ - enum - { - INT, LONG, LONGLONG, - UNSIGNED_INT = 3, UNSIGNED_LONG, UNSIGNED_LONGLONG, - STRING - } type; - long long ll; -}; - -struct printf_args -{ - union printf_arg prealloc[32]; - union printf_arg *ptr; - grub_size_t count; -}; - static void -parse_printf_args (const char *fmt0, struct printf_args *args, +parse_printf_args (const char *fmt0, struct grub_printf_args *args, va_list args_in); static int grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, - struct printf_args *args); + struct grub_printf_args *args); -static void -free_printf_args (struct printf_args *args) +void +grub_free_printf_args (struct grub_printf_args *args) { if (args->ptr != args->prealloc) grub_free (args->ptr); @@ -198,7 +177,7 @@ grub_vprintf (const char *fmt, va_list ap) grub_size_t s; static char buf[PREALLOC_SIZE + 1]; char *curbuf = buf; - struct printf_args args; + struct grub_printf_args args; parse_printf_args (fmt, &args, ap); @@ -219,7 +198,7 @@ grub_vprintf (const char *fmt, va_list ap) s = grub_vsnprintf_real (curbuf, s, fmt, &args); } - free_printf_args (&args); + grub_free_printf_args (&args); grub_xputs (curbuf); @@ -658,13 +637,14 @@ grub_lltoa (char *str, int c, unsigned long long n) * disables positional parameters, "$", because some formats, e.g "%s%1$d", * cannot be validated with the current implementation. * - * The max_args allows to set a maximum number of accepted arguments. If the fmt0 - * string defines more arguments than the max_args then the parse_printf_arg_fmt() - * function returns an error. This is currently used for format check only. + * The max_args allows to set a maximum number of accepted arguments. If the + * fmt0 string defines more arguments than the max_args then the + * grub_parse_printf_arg_fmt() function returns an error. This is currently + * used for format check only. */ -static grub_err_t -parse_printf_arg_fmt (const char *fmt0, struct printf_args *args, - int fmt_check, grub_size_t max_args) +grub_err_t +grub_parse_printf_arg_fmt (const char *fmt0, struct grub_printf_args *args, + int fmt_check, grub_size_t max_args) { const char *fmt; char c; @@ -847,11 +827,12 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args, } static void -parse_printf_args (const char *fmt0, struct printf_args *args, va_list args_in) +parse_printf_args (const char *fmt0, struct grub_printf_args *args, + va_list args_in) { grub_size_t n; - parse_printf_arg_fmt (fmt0, args, 0, 0); + grub_parse_printf_arg_fmt (fmt0, args, 0, 0); for (n = 0; n < args->count; n++) switch (args->ptr[n].type) @@ -892,7 +873,7 @@ write_char (char *str, grub_size_t *count, grub_size_t max_len, unsigned char ch static int grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, - struct printf_args *args) + struct grub_printf_args *args) { char c; grub_size_t n = 0; @@ -1086,7 +1067,7 @@ int grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap) { grub_size_t ret; - struct printf_args args; + struct grub_printf_args args; if (!n) return 0; @@ -1097,7 +1078,7 @@ grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap) ret = grub_vsnprintf_real (str, n, fmt, &args); - free_printf_args (&args); + grub_free_printf_args (&args); return ret < n ? ret : n; } @@ -1120,7 +1101,7 @@ grub_xvasprintf (const char *fmt, va_list ap) { grub_size_t s, as = PREALLOC_SIZE; char *ret; - struct printf_args args; + struct grub_printf_args args; parse_printf_args (fmt, &args, ap); @@ -1129,7 +1110,7 @@ grub_xvasprintf (const char *fmt, va_list ap) ret = grub_malloc (as + 1); if (!ret) { - free_printf_args (&args); + grub_free_printf_args (&args); return NULL; } @@ -1137,7 +1118,7 @@ grub_xvasprintf (const char *fmt, va_list ap) if (s <= as) { - free_printf_args (&args); + grub_free_printf_args (&args); return ret; } @@ -1159,42 +1140,6 @@ grub_xasprintf (const char *fmt, ...) return ret; } -grub_err_t -grub_printf_fmt_check (const char *fmt, const char *fmt_expected) -{ - struct printf_args args_expected, args_fmt; - grub_err_t ret; - grub_size_t n; - - if (fmt == NULL || fmt_expected == NULL) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid format"); - - ret = parse_printf_arg_fmt (fmt_expected, &args_expected, 1, GRUB_SIZE_MAX); - if (ret != GRUB_ERR_NONE) - return ret; - - /* Limit parsing to the number of expected arguments. */ - ret = parse_printf_arg_fmt (fmt, &args_fmt, 1, args_expected.count); - if (ret != GRUB_ERR_NONE) - { - free_printf_args (&args_expected); - return ret; - } - - for (n = 0; n < args_fmt.count; n++) - if (args_fmt.ptr[n].type != args_expected.ptr[n].type) - { - ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments types do not match"); - break; - } - - free_printf_args (&args_expected); - free_printf_args (&args_fmt); - - return ret; -} - - /* Abort GRUB. This function does not return. */ static void __attribute__ ((noreturn)) grub_abort (void) diff --git a/include/grub/gui_string_util.h b/include/grub/gui_string_util.h index 34f9a090d..5cb444f18 100644 --- a/include/grub/gui_string_util.h +++ b/include/grub/gui_string_util.h @@ -30,4 +30,20 @@ char *grub_resolve_relative_path (const char *base, const char *path); char *grub_get_dirname (const char *file_path); +/* + * grub_printf_fmt_check() checks a fmt string for printf() against an + * expected format. It is intended for cases where the fmt string could come + * from an outside source and cannot be trusted. + * + * While expected fmt accepts a printf() format string it should be kept + * as simple as possible. The printf() format strings with positional + * parameters are NOT accepted, neither for fmt nor for fmt_expected. + * + * The fmt is accepted if it has equal or less arguments than fmt_expected + * and if the type of all arguments match. + * + * Returns GRUB_ERR_NONE if fmt is acceptable. + */ +grub_err_t grub_printf_fmt_check (const char *fmt, const char *fmt_expected); + #endif /* GRUB_GUI_STRING_UTIL_HEADER */ diff --git a/include/grub/misc.h b/include/grub/misc.h index 7d2b55196..8443e1593 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -459,21 +459,32 @@ grub_error_load (const struct grub_error_saved *save) grub_errno = save->grub_errno; } -/* - * grub_printf_fmt_checks() a fmt string for printf() against an expected - * format. It is intended for cases where the fmt string could come from - * an outside source and cannot be trusted. - * - * While expected fmt accepts a printf() format string it should be kept - * as simple as possible. The printf() format strings with positional - * parameters are NOT accepted, neither for fmt nor for fmt_expected. - * - * The fmt is accepted if it has equal or less arguments than fmt_expected - * and if the type of all arguments match. - * - * Returns GRUB_ERR_NONE if fmt is acceptable. - */ -grub_err_t EXPORT_FUNC (grub_printf_fmt_check) (const char *fmt, const char *fmt_expected); +union grub_printf_arg +{ + /* Yes, type is also part of union as the moment we fill the value + we don't need to store its type anymore (when we'll need it, we'll + have format spec again. So save some space. */ + enum + { + INT, LONG, LONGLONG, + UNSIGNED_INT = 3, UNSIGNED_LONG, UNSIGNED_LONGLONG, + STRING + } type; + long long ll; +}; + +struct grub_printf_args +{ + union grub_printf_arg prealloc[32]; + union grub_printf_arg *ptr; + grub_size_t count; +}; + +void EXPORT_FUNC(grub_free_printf_args) (struct grub_printf_args *args); +grub_err_t EXPORT_FUNC(grub_parse_printf_arg_fmt) (const char *fmt0, + struct grub_printf_args *args, + int fmt_check, + grub_size_t max_args); #if BOOT_TIME_STATS struct grub_boot_time -- 2.25.1 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel