Back out regex use in python tests, filter the output instead.

This makes it possible to regenerate the test output again.
Also adds an update_test_data target to the Makefile.
This commit is contained in:
Todd C. Miller
2020-11-11 19:04:01 -07:00
parent b2ccbb3a90
commit d688f4d34e
23 changed files with 84 additions and 75 deletions

View File

@@ -223,6 +223,11 @@ check: $(TEST_PROGS)
./check_python_examples ".libs/python_plugin.so"; \ ./check_python_examples ".libs/python_plugin.so"; \
fi fi
update_test_data: $(TEST_PROGS)
@if test X"$(cross_compiling)" != X"yes"; then \
UPDATE_TESTDATA=1 ./check_python_examples ".libs/python_plugin.so"; \
fi
check_python_examples: $(CHECK_PYTHON_EXAMPLES_OBJS) $(LIBPYTHONPLUGIN) check_python_examples: $(CHECK_PYTHON_EXAMPLES_OBJS) $(LIBPYTHONPLUGIN)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_PYTHON_EXAMPLES_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS) $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_PYTHON_EXAMPLES_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)

View File

@@ -145,10 +145,9 @@ py_log_last_error(const char *context_message)
char *message = py_message ? py_create_string_rep(py_message) : NULL; char *message = py_message ? py_create_string_rep(py_message) : NULL;
py_sudo_log(SUDO_CONV_ERROR_MSG, "%s%s(%s) %s\n", py_sudo_log(SUDO_CONV_ERROR_MSG, "%s%s%s\n",
context_message ? context_message : "", context_message ? context_message : "",
context_message && *context_message ? ": " : "", context_message && *context_message ? ": " : "",
py_type ? ((PyTypeObject *)py_type)->tp_name : "None",
message ? message : "(NULL)"); message ? message : "(NULL)");
free(message); free(message);

View File

@@ -469,6 +469,7 @@ _python_plugin_get_class(const char *plugin_path, PyObject *py_module, const cha
py_class = PyObject_GetAttrString(py_module, plugin_class); py_class = PyObject_GetAttrString(py_module, plugin_class);
if (py_class == NULL) { if (py_class == NULL) {
py_sudo_log(SUDO_CONV_ERROR_MSG, "Failed to find plugin class '%s'\n", plugin_class); py_sudo_log(SUDO_CONV_ERROR_MSG, "Failed to find plugin class '%s'\n", plugin_class);
PyErr_Clear();
goto cleanup; goto cleanup;
} }

View File

@@ -22,7 +22,6 @@
#include "config.h" #include "config.h"
#include "sudo_compat.h" #include "sudo_compat.h"
#include <regex.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@@ -1,6 +1,6 @@
sudo.debug was called with arguments: (<DEBUG.ERROR: 2>, 'My demo purpose plugin shows this ERROR level debug message') sudo.debug was called with arguments: (<DEBUG.ERROR: 2>, 'My demo purpose plugin shows this ERROR level debug message')
sudo.debug was called with arguments: (<DEBUG.INFO: 6>, 'My demo purpose plugin shows this INFO level debug message') sudo.debug was called with arguments: (<DEBUG.INFO: 6>, 'My demo purpose plugin shows this INFO level debug message')
LogHandler.emit was called with arguments: (<.*sudo.LogHandler.* LogHandler.emit was called
LogHandler.emit was called with arguments: (<.*sudo.LogHandler.* LogHandler.emit was called
sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),) sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),)
sudo.options_as_dict returned result: \[('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')\] sudo.options_as_dict returned result: [('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')]

View File

@@ -2,10 +2,10 @@ __init__ @ SRC_DIR/example_debugging.py:58 calls C function:
sudo.debug was called with arguments: (<DEBUG.ERROR: 2>, 'My demo purpose plugin shows this ERROR level debug message') sudo.debug was called with arguments: (<DEBUG.ERROR: 2>, 'My demo purpose plugin shows this ERROR level debug message')
__init__ @ SRC_DIR/example_debugging.py:63 calls C function: __init__ @ SRC_DIR/example_debugging.py:63 calls C function:
sudo.debug was called with arguments: (<DEBUG.INFO: 6>, 'My demo purpose plugin shows this INFO level debug message') sudo.debug was called with arguments: (<DEBUG.INFO: 6>, 'My demo purpose plugin shows this INFO level debug message')
handle @ .*/logging/__init__.py:[0-9]* calls C function: handle @ logging/__init__.py calls C function:
LogHandler.emit was called with arguments: (<.*sudo.LogHandler.* LogHandler.emit was called
handle @ .*/logging/__init__.py:[0-9]* calls C function: handle @ logging/__init__.py calls C function:
LogHandler.emit was called with arguments: (<.*sudo.LogHandler.* LogHandler.emit was called
__init__ @ SRC_DIR/example_debugging.py:85 calls C function: __init__ @ SRC_DIR/example_debugging.py:85 calls C function:
sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),) sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),)
sudo.options_as_dict returned result: \[('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')\] sudo.options_as_dict returned result: [('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')]

View File

@@ -2,7 +2,7 @@ __init__ @ SRC_DIR/example_debugging.py:58 debugs:
My demo purpose plugin shows this ERROR level debug message My demo purpose plugin shows this ERROR level debug message
__init__ @ SRC_DIR/example_debugging.py:63 debugs: __init__ @ SRC_DIR/example_debugging.py:63 debugs:
My demo purpose plugin shows this INFO level debug message My demo purpose plugin shows this INFO level debug message
handle @ .*/logging/__init__.py:[0-9]* debugs: handle @ logging/__init__.py debugs:
Python log system shows this ERROR level debug message Python log system shows this ERROR level debug message
handle @ .*/logging/__init__.py:[0-9]* debugs: handle @ logging/__init__.py debugs:
Python log system shows this INFO level debug message Python log system shows this INFO level debug message

View File

@@ -1,2 +1,2 @@
DebugDemoPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@diag', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')\] DebugDemoPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@diag', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
DebugDemoPlugin.__init__ returned result: <example_debugging.DebugDemoPlugin object> DebugDemoPlugin.__init__ returned result: <example_debugging.DebugDemoPlugin object>

View File

@@ -1,4 +1,4 @@
DebugDemoPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@info', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')\] DebugDemoPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@info', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
DebugDemoPlugin.__init__ returned result: <example_debugging.DebugDemoPlugin object> DebugDemoPlugin.__init__ returned result: <example_debugging.DebugDemoPlugin object>
DebugDemoPlugin function 'log_ttyin' is not implemented DebugDemoPlugin function 'log_ttyin' is not implemented
DebugDemoPlugin function 'log_ttyout' is not implemented DebugDemoPlugin function 'log_ttyout' is not implemented

View File

@@ -1,4 +1,4 @@
.* SudoGroupPlugin.__init__ was called with arguments: () [('args', ('ModulePath=SRC_DIR/example_group_plugin.py', 'ClassName=SudoGroupPlugin')), ('version', '1.0')]
SudoGroupPlugin.__init__ returned result: <example_group_plugin.SudoGroupPlugin object> SudoGroupPlugin.__init__ returned result: <example_group_plugin.SudoGroupPlugin object>
SudoGroupPlugin.query was called with arguments: ('user', 'group', ('pw_name', 'pw_passwd', 1001, 101, 'pw_gecos', 'pw_dir', 'pw_shell')) SudoGroupPlugin.query was called with arguments: ('user', 'group', ('pw_name', 'pw_passwd', 1001, 101, 'pw_gecos', 'pw_dir', 'pw_shell'))
SudoGroupPlugin.query returned result: RC.REJECT SudoGroupPlugin.query returned result: RC.REJECT

View File

@@ -1,9 +1,9 @@
-- Plugin STARTED -- -- Plugin STARTED --
EXEC id --help EXEC id --help
EXEC info \[ EXEC info [
"command=/bin/id", "command=/bin/id",
"runas_uid=0" "runas_uid=0"
\] ]
STD IN some standard input STD IN some standard input
STD OUT some standard output STD OUT some standard output
STD ERR some standard error STD ERR some standard error

View File

@@ -1,9 +1,9 @@
-- Plugin STARTED -- -- Plugin STARTED --
EXEC id --help EXEC id --help
EXEC info \[ EXEC info [
"command=/bin/id", "command=/bin/id",
"runas_uid=0" "runas_uid=0"
\] ]
STD IN stdin for plugin 1 STD IN stdin for plugin 1
STD OUT stdout for plugin 1 STD OUT stdout for plugin 1
STD ERR stderr for plugin 1 STD ERR stderr for plugin 1

View File

@@ -1,9 +1,9 @@
-- Plugin STARTED -- -- Plugin STARTED --
EXEC whoami EXEC whoami
EXEC info \[ EXEC info [
"command=/bin/whoami", "command=/bin/whoami",
"runas_uid=1" "runas_uid=1"
\] ]
STD IN stdin for plugin 2 STD IN stdin for plugin 2
STD OUT stdout for plugin 2 STD OUT stdout for plugin 2
STD ERR stderr for plugin 2 STD ERR stderr for plugin 2

View File

@@ -1,8 +1,8 @@
-- Plugin STARTED -- -- Plugin STARTED --
EXEC cmd EXEC cmd
EXEC info \[ EXEC info [
"command=/usr/share/cmd", "command=/usr/share/cmd",
"runas_uid=0" "runas_uid=0"
\] ]
CLOSE Failed to execute, execve returned 1 (EPERM) CLOSE Failed to execute, execve returned 1 (EPERM)
-- Plugin DESTROYED -- -- Plugin DESTROYED --

View File

@@ -1 +1 @@
Failed to construct plugin instance: (FileNotFoundError) \[Errno 2\] No such file or directory: '/some/not/writable/directory/sudo.log' Failed to construct plugin instance: [Errno 2] No such file or directory: '/some/not/writable/directory/sudo.log'

View File

@@ -1,4 +1,4 @@
SudoPolicyPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_policy_plugin.py', 'ClassName=SudoPolicyPlugin')), ('settings', ()), ('user_env', ()), ('user_info', ()), ('version', '1.0')\] SudoPolicyPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_policy_plugin.py', 'ClassName=SudoPolicyPlugin')), ('settings', ()), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
SudoPolicyPlugin.__init__ returned result: <example_policy_plugin.SudoPolicyPlugin object> SudoPolicyPlugin.__init__ returned result: <example_policy_plugin.SudoPolicyPlugin object>
SudoPolicyPlugin.validate was called with arguments: () SudoPolicyPlugin.validate was called with arguments: ()
SudoPolicyPlugin.validate returned result: None SudoPolicyPlugin.validate returned result: None

View File

@@ -1 +1 @@
Failed during loading plugin class: (ImportError) File 'SRC_DIR/example_debugging.py' must be owned by uid 0 Failed during loading plugin class: File 'SRC_DIR/example_debugging.py' must be owned by uid 0

View File

@@ -1,2 +1,2 @@
Failed to find plugin class 'MispelledPluginName' Failed to find plugin class 'MispelledPluginName'
Failed during loading plugin class: (AttributeError) .* has no attribute 'MispelledPluginName' Failed during loading plugin class

View File

@@ -1 +1 @@
Failed during loading plugin class: ([^)]*) No module named 'wrong_path' Failed during loading plugin class: No module named 'wrong_path'

View File

@@ -1,61 +1,61 @@
(APPROVAL 1) Constructed: (APPROVAL 1) Constructed:
{ {
"_id": "(APPROVAL 1)", "_id": "(APPROVAL 1)",
"plugin_options": \[ "plugin_options": [
"ModulePath=SRC_DIR/regress/plugin_approval_test.py", "ModulePath=SRC_DIR/regress/plugin_approval_test.py",
"ClassName=ApprovalTestPlugin", "ClassName=ApprovalTestPlugin",
"Id=1" "Id=1"
\], ],
"settings": \[ "settings": [
"SETTING1=VALUE1", "SETTING1=VALUE1",
"setting2=value2" "setting2=value2"
\], ],
"submit_argv": \[ "submit_argv": [
"sudo", "sudo",
"-u", "-u",
"user", "user",
"whoami", "whoami",
"--help" "--help"
\], ],
"submit_optind": 3, "submit_optind": 3,
"user_env": \[ "user_env": [
"USER_ENV1=VALUE1", "USER_ENV1=VALUE1",
"USER_ENV2=value2" "USER_ENV2=value2"
\], ],
"user_info": \[ "user_info": [
"INFO1=VALUE1", "INFO1=VALUE1",
"info2=value2" "info2=value2"
\], ],
"version": "1.17" "version": "1.17"
} }
(APPROVAL 2) Constructed: (APPROVAL 2) Constructed:
{ {
"_id": "(APPROVAL 2)", "_id": "(APPROVAL 2)",
"plugin_options": \[ "plugin_options": [
"ModulePath=SRC_DIR/regress/plugin_approval_test.py", "ModulePath=SRC_DIR/regress/plugin_approval_test.py",
"ClassName=ApprovalTestPlugin", "ClassName=ApprovalTestPlugin",
"Id=2" "Id=2"
\], ],
"settings": \[ "settings": [
"SETTING1=VALUE1", "SETTING1=VALUE1",
"setting2=value2" "setting2=value2"
\], ],
"submit_argv": \[ "submit_argv": [
"sudo", "sudo",
"-u", "-u",
"user", "user",
"whoami", "whoami",
"--help" "--help"
\], ],
"submit_optind": 3, "submit_optind": 3,
"user_env": \[ "user_env": [
"USER_ENV1=VALUE1", "USER_ENV1=VALUE1",
"USER_ENV2=value2" "USER_ENV2=value2"
\], ],
"user_info": \[ "user_info": [
"INFO1=VALUE1", "INFO1=VALUE1",
"info2=value2" "info2=value2"
\], ],
"version": "1.17" "version": "1.17"
} }
(APPROVAL 1) Show version was called with arguments: (0,) (APPROVAL 1) Show version was called with arguments: (0,)

View File

@@ -1,4 +1,4 @@
PATH before: \[\] (should be empty) PATH before: [] (should be empty)
PATH set: \['path_for_first_plugin'\] PATH set: ['path_for_first_plugin']
PATH before: \[\] (should be empty) PATH before: [] (should be empty)
PATH set: \['path_for_second_plugin'\] PATH set: ['path_for_second_plugin']

View File

@@ -190,7 +190,7 @@ verify_log_lines(const char *reference_path)
char line[1024] = ""; char line[1024] = "";
char stored_str[MAX_OUTPUT] = ""; char stored_str[MAX_OUTPUT] = "";
while(fgets(line, sizeof(line), file) != NULL) { while(fgets(line, sizeof(line), file) != NULL) {
const char *line_data = strstr(line, "] "); // this skips the timestamp and pid at the beginning char *line_data = strstr(line, "] "); // this skips the timestamp and pid at the beginning
VERIFY_NOT_NULL(line_data); // malformed log line VERIFY_NOT_NULL(line_data); // malformed log line
line_data += 2; line_data += 2;
@@ -198,6 +198,28 @@ verify_log_lines(const char *reference_path)
if (line_end) if (line_end)
snprintf(line_end, sizeof(line) - (line_end - line), " object>\n"); snprintf(line_end, sizeof(line) - (line_end - line), " object>\n");
if (strncmp(line_data, "handle @ /", sizeof("handle @ /") - 1) == 0) {
char *start = line_data + sizeof("handle @ ") - 1;
// normalize path to logging/__init__.py
char *logging = strstr(start, "logging/");
if (logging != NULL) {
memmove(start, logging, strlen(logging) + 1);
}
// remove line number
char *colon = strchr(start, ':');
if (colon != NULL) {
size_t len = strspn(colon + 1, "0123456789");
if (len != 0)
memmove(colon, colon + len + 1, strlen(colon + len + 1) + 1);
}
} else if (strncmp(line_data, "LogHandler.emit was called ", 27) == 0) {
// LogHandler.emit argument details vary based on python version
line_data[26] = '\n';
line_data[27] = '\0';
}
VERIFY_TRUE(strlcat(stored_str, line_data, sizeof(stored_str)) < sizeof(stored_str)); // we have enough space in buffer VERIFY_TRUE(strlcat(stored_str, line_data, sizeof(stored_str)) < sizeof(stored_str)); // we have enough space in buffer
} }

View File

@@ -111,24 +111,7 @@ char ** create_str_array(size_t count, ...);
#define VERIFY_STR(actual, expected) \ #define VERIFY_STR(actual, expected) \
do { \ do { \
const char *actual_str = actual; \ const char *actual_str = actual; \
regex_t regex; \ if (!actual_str || strcmp(actual_str, expected) != 0) { \
int result = 0; \
if (!actual_str) { \
result = -1; \
} else if (*expected == '\0') { \
result = strcmp(actual_str, expected); \
} else { \
if ((result = regcomp(&regex, expected, REG_NOSUB)) != 0) { \
char errbuf[1024]; \
regerror(result, &regex, errbuf, sizeof(errbuf)); \
fprintf(stderr, "regcomp failed at %s:%d: %s\npattern: %s\n", \
__FILE__, __LINE__, errbuf, expected); \
} else { \
result = regexec(&regex, actual_str, 0, NULL, 0); \
regfree(&regex); \
} \
} \
if (result != 0) { \
VERIFY_PRINT_MSG("%s", #actual, actual_str ? actual_str : "(null)", #expected, expected, "expected to be"); \ VERIFY_PRINT_MSG("%s", #actual, actual_str ? actual_str : "(null)", #expected, expected, "expected to be"); \
return false; \ return false; \
} \ } \