]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2026-4480/CVE-2026-4408: lib/util: add test_string_sub unittests
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Sat, 9 May 2026 10:02:47 +0000 (22:02 +1200)
committerStefan Metzmacher <metze@samba.org>
Tue, 26 May 2026 12:51:32 +0000 (12:51 +0000)
This demonstrates the logic of talloc_string_sub_{mixed_quoting,unsafe}()

BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
lib/util/tests/test_string_sub.c [new file with mode: 0644]
lib/util/wscript_build
selftest/tests.py

diff --git a/lib/util/tests/test_string_sub.c b/lib/util/tests/test_string_sub.c
new file mode 100644 (file)
index 0000000..da97c1c
--- /dev/null
@@ -0,0 +1,1044 @@
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+#include "replace.h"
+#include <cmocka.h>
+#include "talloc.h"
+
+#include "../substitute.h"
+
+/* set _DEBUG_VERBOSE to print more. */
+#define _DEBUG_VERBOSE
+
+#ifdef _DEBUG_VERBOSE
+#define debug_message(...) print_message(__VA_ARGS__)
+#else
+#define debug_message(...) /* debug_message */
+#endif
+
+
+static int setup_talloc_context(void **state)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(NULL);
+       *state = mem_ctx;
+       return 0;
+}
+
+static int teardown_talloc_context(void **state)
+{
+       TALLOC_CTX *mem_ctx = *state;
+       TALLOC_FREE(mem_ctx);
+       return 0;
+}
+
+struct cmd_expansion {
+       const char *lp_cmd;
+       const char *username;
+       const char *result_cmd;
+       bool modified;
+       bool masked;
+       bool mixed_fallback;
+};
+
+static void _test_talloc_string_sub_unsafe(void **state,
+                                          struct cmd_expansion expansions[],
+                                          size_t n_expansions,
+                                          const char *unsafe_characters)
+{
+       TALLOC_CTX *mem_ctx = *state;
+       size_t i;
+
+       for (i = 0; i < n_expansions; i++) {
+               struct cmd_expansion t = expansions[i];
+               char *result_cmd = NULL;
+               bool masked;
+               bool mixed_fallback;
+               bool modified;
+               bool flags_correct;
+               bool mixed;
+               int cmp;
+
+               mixed = talloc_string_sub_mixed_quoting(t.lp_cmd, 'u');
+
+               result_cmd = talloc_string_sub_unsafe(mem_ctx,
+                                                     t.lp_cmd,
+                                                     'u',
+                                                     t.username,
+                                                     unsafe_characters,
+                                                     '_',
+                                                     "FallbackUsername",
+                                                     &modified,
+                                                     &masked,
+                                                     &mixed_fallback);
+               assert_ptr_not_equal(result_cmd, NULL);
+               assert_ptr_not_equal(t.result_cmd, NULL);
+
+               cmp = strcmp(t.result_cmd, result_cmd);
+               flags_correct = (modified == t.modified &&
+                                masked == t.masked &&
+                                mixed_fallback == t.mixed_fallback);
+
+               if (cmp == 0) {
+                       debug_message("[%zu] «%s» «%s»   ->   «%s»; AS EXPECTED\n",
+                                     i, t.lp_cmd,
+                                     t.username,
+                                     result_cmd);
+               } else {
+                       debug_message("[%zu] «%s» «%s»; "
+                                     "expected   [%zu] «%s»   got  [%zu] «%s»\033[1;31m BAD! \033[0m\n",
+                                     i, t.lp_cmd,
+                                     t.username,
+                                     strlen(t.result_cmd), t.result_cmd,
+                                     strlen(result_cmd), result_cmd);
+               }
+               assert_int_equal(cmp, 0);
+               if (!flags_correct) {
+                       debug_message("[%zu] ", i);
+#define _FLAG(x) debug_message((t. x  == x) ? "%s: %s √; ":          \
+                              "%s \033[1;31m expected %s \033[0m; ",   \
+                              #x, t.x ? "true": "false");
+                       _FLAG(modified);
+                       _FLAG(masked);
+                       _FLAG(mixed_fallback);
+                       debug_message("\n");
+               }
+               assert_int_equal(flags_correct, true);
+               if (mixed_fallback != mixed) {
+                       debug_message("[%zu] %s mixed \033[1;31m expected %s \033[0m; ",
+                                     i, t.lp_cmd,
+                                     mixed_fallback ? "true": "false");
+               }
+               assert_int_equal(mixed_fallback, mixed);
+#undef _FLAG
+       }
+       debug_message("ALL correct\n");
+}
+
+static void test_talloc_string_sub_unsafe(void **state)
+{
+       const char *unsafe_characters = STRING_SUB_UNSAFE_CHARACTERS;
+
+       static struct cmd_expansion expansions[] = {
+               {
+                       "/bin/echo \"bob'",
+                       "bob",
+                       "/bin/echo \"bob'",
+                       false,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "bob",
+                       "/bin/echo 'bob'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "bob",
+                       "/bin/echo 'bob'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "bob'",
+                       "/bin/echo 'bob_'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "bob'''",
+                       "/bin/echo 'bob___'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "bob\'",
+                       "/bin/echo 'bob_'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo '%u",
+                       "bob bob bob",
+                       "/bin/echo 'FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo \"%u\"",
+                       " ",
+                       "/bin/echo ' '",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"--uu=%u\"",
+                       "bob",
+                       "/bin/echo \"--uu=FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo \"--uu=%u\"",
+                       "bob !0",
+                       "/bin/echo \"--uu=FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo %u",
+                       "!0",
+                       "/bin/echo '!0'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"--uu=%u\"",
+                       "bob \\",
+                       "/bin/echo \"--uu=FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "bob >> x",
+                       "/bin/echo --uu='bob __ x'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo '--uu=%u\"",
+                       "bob",
+                       "/bin/echo '--uu=FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "bob",
+                       "/bin/echo --uu='bob'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo --uu'=%u'",
+                       "bob",
+                       "/bin/echo --uu'=FallbackUsername'",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu'=%u'",
+                       "`ls`",
+                       "/bin/echo --uu'=FallbackUsername'",
+                       true,
+                       true,
+                       true,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "u%u%u%u%u",
+                       "/bin/echo --uu='u_u_u_u_u'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "$(ls)",
+                       "/bin/echo --uu='_(ls)'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "`ls`",
+                       "/bin/echo --uu='_ls_'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo --uu='1' %u",
+                       "`ls`",
+                       "/bin/echo --uu='1' FallbackUsername",
+                       true,
+                       true,
+                       true,
+               },
+               {
+                       "/bin/echo --uu=\"'%u'\"",
+                       "bob",
+                       "/bin/echo --uu=\"'bob'\"",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo --uu='%u' --yy='%u' '%u' %u",
+                       "bob",
+                       "/bin/echo --uu='bob' --yy='bob' 'bob' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu=%u%u%u'' %user 50%u",
+                       "bob",
+                       "/bin/echo --uu=FallbackUsernameFallbackUsernameFallbackUsername'' FallbackUsernameser 50FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo %u",
+                       "!!",
+                       "/bin/echo '!!'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       ">xxx",
+                       "/bin/echo '_xxx'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "3",
+                       "/bin/echo '3'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "3$",
+                       "/bin/echo '3_'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "comp$",
+                       "/bin/echo 'comp_'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "3$3",
+                       "/bin/echo '3_3'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "q $3",
+                       "/bin/echo 'q _3'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo '%u",
+                       "q $3",
+                       "/bin/echo 'FallbackUsername",
+                       true,
+                       true,
+                       true,
+               },
+               {
+                       "/bin/echo -s '%u' %u",
+                       "āāā",
+                       "/bin/echo -s 'āāā' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo -s '%u' %u",
+                       "-āāā",
+                       "/bin/echo -s '_āāā' FallbackUsername",
+                       true,
+                       true,
+                       true,
+               },
+               {
+                       "/bin/echo -s %u",
+                       "āāā",
+                       "/bin/echo -s 'āāā'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo -s %u",
+                       "a -a",
+                       "/bin/echo -s 'a -a'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo -s=%u %u",
+                       "ā -a",
+                       "/bin/echo -s='ā -a' 'ā -a'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo -s=\"%u %u\"",
+                       "ā -a",
+                       "/bin/echo -s=\"FallbackUsername FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo -m='fridge' %u",
+                       "ā  -ß",
+                       "/bin/echo -m='fridge' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo -m='fridge' %u",
+                       "-ā -a",
+                       "/bin/echo -m='fridge' FallbackUsername",
+                       true,
+                       true,
+                       true,
+               },
+               {
+                       "/bin/echo %u",
+                       "-n",
+                       "/bin/echo '_n'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "o'clock",
+                       "/bin/echo 'o_clock'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo \"bob'",
+                       "bob",
+                       "/bin/echo \"bob'",
+                       false,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"%u\"",
+                       "%u",
+                       "/bin/echo '_u'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo \"$(ls)\"",
+                       "%u",
+                       "/bin/echo \"$(ls)\"",
+                       false,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "\\",
+                       "/bin/echo '\\'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "\\",
+                       "/bin/echo '\\'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"%u\"",
+                       "\\",
+                       "/bin/echo '\\'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"%u\" %u",
+                       "\\",
+                       "/bin/echo '\\' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo '%u' \"%u\" %u",
+                       "\\",
+                       "/bin/echo '\\' \"FallbackUsername\" FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo '%u' \"%u\"",
+                       "bob",
+                       "/bin/echo 'bob' \"FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+       };
+
+       _test_talloc_string_sub_unsafe(state,
+                                      expansions,
+                                      ARRAY_SIZE(expansions),
+                                      unsafe_characters);
+}
+
+static void test_talloc_string_sub_unsafe_minimal_unsafe_chars(void **state)
+{
+       const char *unsafe_characters = "\"'%";
+
+       static struct cmd_expansion expansions[] = {
+               {
+                       "/bin/echo \"bob'",
+                       "bob",
+                       "/bin/echo \"bob'",
+                       false,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "bob",
+                       "/bin/echo 'bob'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "bob",
+                       "/bin/echo 'bob'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "bob'",
+                       "/bin/echo 'bob_'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "bob'''",
+                       "/bin/echo 'bob___'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "bob\'",
+                       "/bin/echo 'bob_'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo '%u",
+                       "bob bob bob",
+                       "/bin/echo 'FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo \"%u\"",
+                       " ",
+                       "/bin/echo ' '",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"--uu=%u\"",
+                       "bob",
+                       "/bin/echo \"--uu=FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo \"--uu=%u\"",
+                       "bob !0",
+                       "/bin/echo \"--uu=FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo %u",
+                       "!0",
+                       "/bin/echo '!0'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"--uu=%u\"",
+                       "bob \\",
+                       "/bin/echo \"--uu=FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "bob >> x",
+                       "/bin/echo --uu='bob >> x'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '--uu=%u\"",
+                       "bob",
+                       "/bin/echo '--uu=FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "bob",
+                       "/bin/echo --uu='bob'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo --uu'=%u'",
+                       "bob",
+                       "/bin/echo --uu'=FallbackUsername'",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu'=%u'",
+                       "`ls`",
+                       "/bin/echo --uu'=FallbackUsername'",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "u%u%u%u%u",
+                       "/bin/echo --uu='u_u_u_u_u'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "$(ls)",
+                       "/bin/echo --uu='$(ls)'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo --uu='%u'",
+                       "`ls`",
+                       "/bin/echo --uu='`ls`'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo --uu='1' %u",
+                       "`ls`",
+                       "/bin/echo --uu='1' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu=\"'%u'\"",
+                       "bob",
+                       "/bin/echo --uu=\"'bob'\"",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo --uu='%u' --yy='%u' '%u' %u",
+                       "bob",
+                       "/bin/echo --uu='bob' --yy='bob' 'bob' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo --uu=%u%u%u'' %user 50%u",
+                       "bob",
+                       "/bin/echo --uu=FallbackUsernameFallbackUsernameFallbackUsername'' FallbackUsernameser 50FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo %u",
+                       "!!",
+                       "/bin/echo '!!'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       ">xxx",
+                       "/bin/echo '>xxx'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "3",
+                       "/bin/echo '3'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "3$",
+                       "/bin/echo '3$'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "comp$",
+                       "/bin/echo 'comp$'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "3$3",
+                       "/bin/echo '3$3'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "q $3",
+                       "/bin/echo 'q $3'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u",
+                       "q $3",
+                       "/bin/echo 'FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo -s '%u' %u",
+                       "āāā",
+                       "/bin/echo -s 'āāā' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo -s '%u' %u",
+                       "-āāā",
+                       "/bin/echo -s '_āāā' FallbackUsername",
+                       true,
+                       true,
+                       true,
+               },
+               {
+                       "/bin/echo -s %u",
+                       "āāā",
+                       "/bin/echo -s 'āāā'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo -s %u",
+                       "a -a",
+                       "/bin/echo -s 'a -a'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo -s=%u %u",
+                       "ā -a",
+                       "/bin/echo -s='ā -a' 'ā -a'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo -s=\"%u %u\"",
+                       "ā -a",
+                       "/bin/echo -s=\"FallbackUsername FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo -m='fridge' %u",
+                       "ā  -ß",
+                       "/bin/echo -m='fridge' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo -m='fridge' %u",
+                       "-ā -a",
+                       "/bin/echo -m='fridge' FallbackUsername",
+                       true,
+                       true,
+                       true,
+               },
+               {
+                       "/bin/echo %u",
+                       "-n",
+                       "/bin/echo '_n'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "o'clock",
+                       "/bin/echo 'o_clock'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo \"bob'",
+                       "bob",
+                       "/bin/echo \"bob'",
+                       false,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"%u\"",
+                       "%u",
+                       "/bin/echo '_u'",
+                       true,
+                       true,
+                       false,
+               },
+               {
+                       "/bin/echo \"$(ls)\"",
+                       "%u",
+                       "/bin/echo \"$(ls)\"",
+                       false,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo %u",
+                       "\\",
+                       "/bin/echo '\\'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo '%u'",
+                       "\\",
+                       "/bin/echo '\\'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"%u\"",
+                       "\\",
+                       "/bin/echo '\\'",
+                       true,
+                       false,
+                       false,
+               },
+               {
+                       "/bin/echo \"%u\" %u",
+                       "\\",
+                       "/bin/echo '\\' FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo '%u' \"%u\" %u",
+                       "\\",
+                       "/bin/echo '\\' \"FallbackUsername\" FallbackUsername",
+                       true,
+                       false,
+                       true,
+               },
+               {
+                       "/bin/echo '%u' \"%u\"",
+                       "bob",
+                       "/bin/echo 'bob' \"FallbackUsername\"",
+                       true,
+                       false,
+                       true,
+               },
+       };
+
+       _test_talloc_string_sub_unsafe(state,
+                                      expansions,
+                                      ARRAY_SIZE(expansions),
+                                      unsafe_characters);
+}
+
+static void test_talloc_string_sub_unsafe_all_mixes(void **state)
+{
+       const char *unsafe_characters = STRING_SUB_UNSAFE_CHARACTERS;
+       size_t i;
+
+       for (i = 0; i < 32; i++) {
+               char in[100] = { 0, };
+               char out[100] = { 0, };
+               struct cmd_expansion expansions[] = {
+                       {
+                               in,
+                               "bob",
+                               out,
+                               true,
+                               false,
+                               false,
+                       },
+               };
+               bool vsq = i & 1;
+               bool vdq = i & 2;
+               bool v = i & 4;
+               bool sq = i & 8;
+               bool dq = i & 16;
+               char *inp = in;
+               char *outp = out;
+               if (vsq) {
+                       inp = stpcpy(inp, "'%u' ");
+                       outp = stpcpy(outp, "'bob' ");
+                       debug_message("vsq ");
+               }
+               if (vdq) {
+                       inp = stpcpy(inp, "\"%u\" ");
+                       outp = stpcpy(outp, (vsq || sq) ? "\"FallbackUsername\" " : "'bob' ");
+                       debug_message("vdq ");
+                       if (vsq || sq) {
+                               expansions[0].mixed_fallback = true;
+                       }
+               }
+               if (v) {
+                       inp = stpcpy(inp, "%u ");
+                       outp = stpcpy(outp, (vsq || vdq || sq || dq) ? "FallbackUsername " : "'bob' ");
+                       debug_message("v ");
+                       if (vsq || vdq || sq || dq) {
+                               expansions[0].mixed_fallback = true;
+                       }
+               }
+               if (sq) {
+                       inp = stpcpy(inp, "' ");
+                       outp = stpcpy(outp, "' ");
+                       debug_message("sq ");
+               }
+               if (dq) {
+                       inp = stpcpy(inp, "\" ");
+                       outp = stpcpy(outp, "\" ");
+                       debug_message("dq ");
+               }
+               debug_message("(i: %zu)\n", i);
+               *inp = '\0';
+               *outp = '\0';
+               expansions[0].modified = strcmp(in, out) != 0;
+
+               _test_talloc_string_sub_unsafe(state,
+                                              expansions,
+                                              ARRAY_SIZE(expansions),
+                                              unsafe_characters);
+       }
+}
+
+
+int main(void)
+{
+       const struct CMUnitTest tests[] = {
+               cmocka_unit_test(test_talloc_string_sub_unsafe),
+               cmocka_unit_test(test_talloc_string_sub_unsafe_minimal_unsafe_chars),
+               cmocka_unit_test(test_talloc_string_sub_unsafe_all_mixes),
+       };
+       if (!isatty(1)) {
+               cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+       }
+       return cmocka_run_group_tests(tests,
+                                     setup_talloc_context,
+                                     teardown_talloc_context);
+}
index 3e96c6caf5f8a4ff5fe2d284596c48b0a7a1b2af..9b43d05960b6c402cdc7f133c77d55e9485aa88b 100644 (file)
@@ -427,3 +427,9 @@ else:
                      deps='cmocka replace talloc stable_sort',
                      local_include=False,
                      for_selftest=True)
+
+    bld.SAMBA3_BINARY('test_string_sub',
+                      source='tests/test_string_sub.c',
+                      deps='''cmocka replace talloc samba-util
+                      ''',
+                      for_selftest=True)
index 0695ac67ea16111a344944d4f63022aa764ebcb5..0a369e4c47a509b6cb2dac9340da67ec08c48c7c 100644 (file)
@@ -560,6 +560,8 @@ plantestsuite("samba.unittests.json_logging", "none",
               [os.path.join(bindir(), "default/lib/util/test_json_logging")])
 plantestsuite("samba.unittests.stable_sort", "none",
               [os.path.join(bindir(), "default/lib/util/test_stable_sort")])
+plantestsuite("samba.unittests.test_string_sub", "none",
+              [os.path.join(bindir(), "test_string_sub")])
 plantestsuite("samba.unittests.ntlm_check", "none",
               [os.path.join(bindir(), "default/libcli/auth/test_ntlm_check")])
 plantestsuite("samba.unittests.gnutls", "none",