mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-22 01:49:11 +00:00
Treat a lone backslash at the end of a string as a literal backslash.
GitHub issue #99
This commit is contained in:
parent
d6d2e3488b
commit
5e5131dec3
1
MANIFEST
1
MANIFEST
@ -742,6 +742,7 @@ plugins/sudoers/regress/cvtsudoers/test8.out.ok
|
|||||||
plugins/sudoers/regress/cvtsudoers/test8.sh
|
plugins/sudoers/regress/cvtsudoers/test8.sh
|
||||||
plugins/sudoers/regress/cvtsudoers/test9.out.ok
|
plugins/sudoers/regress/cvtsudoers/test9.out.ok
|
||||||
plugins/sudoers/regress/cvtsudoers/test9.sh
|
plugins/sudoers/regress/cvtsudoers/test9.sh
|
||||||
|
plugins/sudoers/regress/editor/check_editor.c
|
||||||
plugins/sudoers/regress/env_match/check_env_pattern.c
|
plugins/sudoers/regress/env_match/check_env_pattern.c
|
||||||
plugins/sudoers/regress/env_match/data
|
plugins/sudoers/regress/env_match/data
|
||||||
plugins/sudoers/regress/exptilde/check_exptilde.c
|
plugins/sudoers/regress/exptilde/check_exptilde.c
|
||||||
|
@ -155,9 +155,10 @@ SHELL = @SHELL@
|
|||||||
PROGS = sudoers.la visudo sudoreplay cvtsudoers testsudoers
|
PROGS = sudoers.la visudo sudoreplay cvtsudoers testsudoers
|
||||||
|
|
||||||
# Regression tests
|
# Regression tests
|
||||||
TEST_PROGS = check_addr check_base64 check_digest check_env_pattern \
|
TEST_PROGS = check_addr check_base64 check_digest check_editor \
|
||||||
check_exptilde check_fill check_gentime check_hexchar \
|
check_env_pattern check_exptilde check_fill check_gentime \
|
||||||
check_iolog_plugin check_starttime check_unesc @SUDOERS_TEST_PROGS@
|
check_hexchar check_iolog_plugin check_starttime \
|
||||||
|
check_unesc @SUDOERS_TEST_PROGS@
|
||||||
|
|
||||||
# Fuzzers
|
# Fuzzers
|
||||||
LIB_FUZZING_ENGINE = @FUZZ_ENGINE@
|
LIB_FUZZING_ENGINE = @FUZZ_ENGINE@
|
||||||
@ -224,6 +225,8 @@ CHECK_BASE64_OBJS = check_base64.o b64_decode.lo b64_encode.o sudoers_debug.lo
|
|||||||
|
|
||||||
CHECK_DIGEST_OBJS = check_digest.o filedigest.lo digestname.lo sudoers_debug.lo
|
CHECK_DIGEST_OBJS = check_digest.o filedigest.lo digestname.lo sudoers_debug.lo
|
||||||
|
|
||||||
|
CHECK_EDITOR_OBJS = check_editor.o editor.lo sudoers_debug.lo
|
||||||
|
|
||||||
CHECK_ENV_MATCH_OBJS = check_env_pattern.o env_pattern.lo sudoers_debug.lo
|
CHECK_ENV_MATCH_OBJS = check_env_pattern.o env_pattern.lo sudoers_debug.lo
|
||||||
|
|
||||||
CHECK_EXPTILDE_OBJS = check_exptilde.o exptilde.lo pwutil.lo pwutil_impl.lo redblack.lo sudoers_debug.lo
|
CHECK_EXPTILDE_OBJS = check_exptilde.o exptilde.lo pwutil.lo pwutil_impl.lo redblack.lo sudoers_debug.lo
|
||||||
@ -360,6 +363,9 @@ check_base64: $(CHECK_BASE64_OBJS) $(LIBUTIL)
|
|||||||
check_digest: $(CHECK_DIGEST_OBJS) $(LIBUTIL)
|
check_digest: $(CHECK_DIGEST_OBJS) $(LIBUTIL)
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_DIGEST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_DIGEST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
check_editor: $(CHECK_EDITOR_OBJS) $(LIBUTIL)
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_EDITOR_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
check_env_pattern: $(CHECK_ENV_MATCH_OBJS) $(LIBUTIL)
|
check_env_pattern: $(CHECK_ENV_MATCH_OBJS) $(LIBUTIL)
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_ENV_MATCH_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_ENV_MATCH_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
@ -1118,6 +1124,30 @@ check_digest.i: $(srcdir)/regress/parser/check_digest.c \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
check_digest.plog: check_digest.i
|
check_digest.plog: check_digest.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parser/check_digest.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parser/check_digest.c --i-file $< --output-file $@
|
||||||
|
check_editor.o: $(srcdir)/regress/editor/check_editor.c $(devdir)/def_data.c \
|
||||||
|
$(devdir)/def_data.h $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||||
|
$(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||||
|
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||||
|
$(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
|
||||||
|
$(srcdir)/parse.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
|
||||||
|
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
|
||||||
|
$(top_builddir)/pathnames.h
|
||||||
|
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/editor/check_editor.c
|
||||||
|
check_editor.i: $(srcdir)/regress/editor/check_editor.c $(devdir)/def_data.c \
|
||||||
|
$(devdir)/def_data.h $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||||
|
$(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||||
|
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||||
|
$(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
|
||||||
|
$(srcdir)/parse.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
|
||||||
|
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
|
||||||
|
$(top_builddir)/pathnames.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
check_editor.plog: check_editor.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/editor/check_editor.c --i-file $< --output-file $@
|
||||||
check_env_pattern.o: $(srcdir)/regress/env_match/check_env_pattern.c \
|
check_env_pattern.o: $(srcdir)/regress/env_match/check_env_pattern.c \
|
||||||
$(devdir)/def_data.h $(incdir)/compat/stdbool.h \
|
$(devdir)/def_data.h $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||||
|
@ -41,7 +41,7 @@ static const char *
|
|||||||
wordsplit(const char *str, const char *endstr, const char **last)
|
wordsplit(const char *str, const char *endstr, const char **last)
|
||||||
{
|
{
|
||||||
const char *cp;
|
const char *cp;
|
||||||
debug_decl(wordsplit, SUDO_DEBUG_UTIL);
|
debug_decl(wordsplit, SUDOERS_DEBUG_UTIL);
|
||||||
|
|
||||||
/* If no str specified, use last ptr (if any). */
|
/* If no str specified, use last ptr (if any). */
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
@ -72,7 +72,7 @@ wordsplit(const char *str, const char *endstr, const char **last)
|
|||||||
|
|
||||||
/* Scan str until we encounter white space. */
|
/* Scan str until we encounter white space. */
|
||||||
for (cp = str; cp < endstr; cp++) {
|
for (cp = str; cp < endstr; cp++) {
|
||||||
if (*cp == '\\') {
|
if (cp[0] == '\\' && cp[1] != '\0') {
|
||||||
/* quoted char, do not interpret */
|
/* quoted char, do not interpret */
|
||||||
cp++;
|
cp++;
|
||||||
continue;
|
continue;
|
||||||
@ -96,7 +96,7 @@ copy_arg(const char *src, size_t len)
|
|||||||
|
|
||||||
if ((copy = malloc(len + 1)) != NULL) {
|
if ((copy = malloc(len + 1)) != NULL) {
|
||||||
for (dst = copy; src < src_end; ) {
|
for (dst = copy; src < src_end; ) {
|
||||||
if (*src == '\\') {
|
if (src[0] == '\\' && src[1] != '\0') {
|
||||||
src++;
|
src++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
142
plugins/sudoers/regress/editor/check_editor.c
Normal file
142
plugins/sudoers/regress/editor/check_editor.c
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define SUDO_ERROR_WRAP 0
|
||||||
|
|
||||||
|
#include "sudoers.h"
|
||||||
|
#include <def_data.c>
|
||||||
|
|
||||||
|
/* Note hard-coded array lengths. */
|
||||||
|
struct test_data {
|
||||||
|
char *editor_var;
|
||||||
|
int nfiles;
|
||||||
|
char *files[4];
|
||||||
|
char *editor_path;
|
||||||
|
int edit_argc;
|
||||||
|
char *edit_argv[10];
|
||||||
|
} test_data[] = {
|
||||||
|
{
|
||||||
|
/* Bug #942 */
|
||||||
|
"SUDO_EDITOR=sh -c \"vi \\$1\"",
|
||||||
|
1,
|
||||||
|
{ "/etc/motd", NULL },
|
||||||
|
"/usr/bin/sh",
|
||||||
|
5,
|
||||||
|
{ "sh", "-c", "vi $1", "--", "/etc/motd", NULL }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* GitHub issue #99 */
|
||||||
|
"EDITOR=/usr/bin/vi\\",
|
||||||
|
1,
|
||||||
|
{ "/etc/hosts", "/bogus/file", NULL },
|
||||||
|
"/usr/bin/vi\\",
|
||||||
|
3,
|
||||||
|
{ "/usr/bin/vi\\", "--", "/etc/hosts", "/bogus/file", NULL }
|
||||||
|
},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
sudo_dso_public int main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
/* STUB */
|
||||||
|
int
|
||||||
|
find_path(const char *infile, char **outfile, struct stat *sbp,
|
||||||
|
const char *path, const char *runchroot, int ignore_dot,
|
||||||
|
char * const *allowlist)
|
||||||
|
{
|
||||||
|
if (infile[0] == '/') {
|
||||||
|
*outfile = strdup(infile);
|
||||||
|
} else {
|
||||||
|
if (asprintf(outfile, "/usr/bin/%s", infile) == -1)
|
||||||
|
*outfile = NULL;
|
||||||
|
}
|
||||||
|
if (*outfile == NULL)
|
||||||
|
return NOT_FOUND_ERROR;
|
||||||
|
return FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct test_data *data;
|
||||||
|
int ntests = 0, errors = 0;
|
||||||
|
|
||||||
|
initprogname(argc > 0 ? argv[0] : "check_editor");
|
||||||
|
|
||||||
|
for (data = test_data; data->editor_var != NULL; data++) {
|
||||||
|
const char *env_editor = NULL;
|
||||||
|
char *cp, *editor_path, **edit_argv = NULL;
|
||||||
|
int i, edit_argc = 0;
|
||||||
|
|
||||||
|
/* clear existing editor environment vars */
|
||||||
|
putenv("VISUAL=");
|
||||||
|
putenv("EDITOR=");
|
||||||
|
putenv("SUDO_EDITOR=");
|
||||||
|
|
||||||
|
putenv(data->editor_var);
|
||||||
|
editor_path = find_editor(data->nfiles, data->files, &edit_argc,
|
||||||
|
&edit_argv, NULL, &env_editor, false);
|
||||||
|
ntests++;
|
||||||
|
if (strcmp(editor_path, data->editor_path) != 0) {
|
||||||
|
sudo_warnx("test %d: editor_path: expected \"%s\", got \"%s\"",
|
||||||
|
ntests, data->editor_path, editor_path);
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
ntests++;
|
||||||
|
cp = strchr(data->editor_var, '=') + 1;
|
||||||
|
if (strcmp(env_editor, cp) != 0) {
|
||||||
|
sudo_warnx("test %d: env_editor: expected \"%s\", got \"%s\"",
|
||||||
|
ntests, cp, env_editor ? env_editor : "(NULL)");
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
ntests++;
|
||||||
|
if (edit_argc != data->edit_argc) {
|
||||||
|
sudo_warnx("test %d: edit_argc: expected %d, got %d",
|
||||||
|
ntests, data->edit_argc, edit_argc);
|
||||||
|
errors++;
|
||||||
|
} else {
|
||||||
|
ntests++;
|
||||||
|
for (i = 0; i < edit_argc; i++) {
|
||||||
|
if (strcmp(edit_argv[i], data->edit_argv[i]) != 0) {
|
||||||
|
sudo_warnx("test %d: edit_argv[%d]: expected \"%s\", got \"%s\"",
|
||||||
|
ntests, i, data->edit_argv[i], edit_argv[i]);
|
||||||
|
errors++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(editor_path);
|
||||||
|
edit_argc -= data->nfiles + 1;
|
||||||
|
for (i = 0; i < edit_argc; i++) {
|
||||||
|
free(edit_argv[i]);
|
||||||
|
}
|
||||||
|
free(edit_argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s: %d tests run, %d errors, %d%% success rate\n", getprogname(),
|
||||||
|
ntests, errors, (ntests - errors) * 100 / ntests);
|
||||||
|
|
||||||
|
exit(errors);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user