From: Willy Tarreau Date: Tue, 24 Jun 2025 15:18:52 +0000 (+0200) Subject: MINOR: tools: add env_suggest() to suggest alternate variable names X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=14087e48b97dae5e84b0557394a15c6794100d4e;p=thirdparty%2Fhaproxy.git MINOR: tools: add env_suggest() to suggest alternate variable names The purpose here is to look in the environment for a variable whose name looks like the provided one. This will be used to try to auto- correct misspelled environment variables that would silently be turned to an empty string. --- diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index 931f71506..bacde6dde 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -1022,6 +1022,7 @@ int my_unsetenv(const char *name); * some expansion is made. */ char *env_expand(char *in); +struct ist env_suggest(struct ist word); int is_path_mode(mode_t mode, const char *path_fmt, ...); int is_file_present(const char *path_fmt, ...); int is_dir_present(const char *path_fmt, ...); diff --git a/src/tools.c b/src/tools.c index 093e691b9..9f1d780d3 100644 --- a/src/tools.c +++ b/src/tools.c @@ -6667,6 +6667,43 @@ void update_word_fingerprint(uint8_t *fp, const char *word) return update_word_fingerprint_with_len(fp, ist(word)); } +/* tries to find in the environment a similar looking variable name as the one + * in , and returns it otherwise NULL. may be NULL or empty. + */ +struct ist env_suggest(struct ist word) +{ + uint8_t word_sig[1024]; + uint8_t name_sig[1024]; + int dist, best_dist = INT_MAX; + char **curr_env; + + struct ist curr_name, best_name = IST_NULL; + + if (!isttest(word)) + return IST_NULL; + + make_word_fingerprint_with_len(word_sig, word); + for (curr_env = environ; *curr_env; curr_env++) { + curr_name = ist(*curr_env); + curr_name.len -= istfind(curr_name, '=').len; + make_word_fingerprint_with_len(name_sig, curr_name); + dist = word_fingerprint_distance(word_sig, name_sig); + if (dist < best_dist) { + best_dist = dist; + best_name = curr_name; + } + } + + /* eliminate too different ones, with more tolerance for prefixes + * when they're known to exist (not from extra list). + */ + if (isttest(best_name) && + (best_dist > 2 * istlen(word) || best_dist > 2 * istlen(best_name))) + best_name = IST_NULL; + return best_name; +} + + /* This function hashes a word, scramble is the anonymizing key, returns * the hashed word when the key (scramble) != 0, else returns the word. * This function can be called NB_L_HASH_WORD times in a row, don't call