1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 13:11:28 +00:00
Files
nmap/nbase/test/test-escape_windows_command_arg.c
2013-07-02 16:56:03 +00:00

205 lines
5.0 KiB
C

/*
Usage: test-escape_windows_command_arg.exe
This is a test program for the escape_windows_command_arg function from
nbase_str.c. Its code is strictly Windows-specific. Basically, it performs
escape_windows_command_arg on arrays of strings merging its results with spaces
and tests if an attempt to decode them with CommandLineToArgvW results in the
same strings.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "nbase.h"
#include <shellapi.h>
const char *TESTS[][5] = {
{ NULL },
{"", NULL},
{"", "", NULL},
{"1", "2", "3", "4", NULL},
{"a", "b", "c", NULL},
{"a b", "c", NULL},
{"a b c", NULL},
{" a b c ", NULL},
{"\"quote\"", NULL},
{"back\\slash", NULL},
{"backslash at end\\", NULL},
{"double\"\"quote", NULL},
{" a\nb\tc\rd\ne", NULL},
{"..\\test\\toupper.lua", NULL},
{"backslash at end\\", "som\\ething\"af\\te\\r", NULL},
{"three\\\\\\backslashes", "som\\ething\"af\\te\\r", NULL},
{"three\"\"\"quotes", "som\\ething\"af\\te\\r", NULL},
};
static LPWSTR utf8_to_wchar(const char *s)
{
LPWSTR result;
int size, ret;
/* Get needed buffer size. */
size = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
if (size == 0) {
fprintf(stderr, "MultiByteToWideChar 1 failed: %d\n", GetLastError());
exit(1);
}
result = (LPWSTR) malloc(sizeof(*result) * size);
ret = MultiByteToWideChar(CP_UTF8, 0, s, -1, result, size);
if (ret == 0) {
fprintf(stderr, "MultiByteToWideChar 2 failed: %d\n", GetLastError());
exit(1);
}
return result;
}
static char *wchar_to_utf8(const LPWSTR s)
{
char *result;
int size, ret;
/* Get needed buffer size. */
size = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
if (size == 0) {
fprintf(stderr, "WideCharToMultiByte 1 failed: %d\n", GetLastError());
exit(1);
}
result = (char *) malloc(size);
ret = WideCharToMultiByte(CP_UTF8, 0, s, -1, result, size, NULL, NULL);
if (ret == 0) {
fprintf(stderr, "WideCharToMultiByte 2 failed: %d\n", GetLastError());
exit(1);
}
return result;
}
static char **wchar_to_utf8_array(const LPWSTR a[], unsigned int len)
{
char **result;
unsigned int i;
result = (char **) malloc(sizeof(*result) * len);
if (result == NULL)
return NULL;
for (i = 0; i < len; i++)
result[i] = wchar_to_utf8(a[i]);
return result;
}
static unsigned int nullarray_length(const char *a[])
{
unsigned int i;
for (i = 0; a[i] != NULL; i++)
;
return i;
}
static char *append(char *p, const char *s)
{
size_t plen, slen;
plen = strlen(p);
slen = strlen(s);
p = (char *) realloc(p, plen + slen + 1);
if (p == NULL)
return NULL;
return strncat(p, s, plen+slen);
}
/* Turns an array of strings into an escaped flat command line. */
static LPWSTR build_commandline(const char *args[], unsigned int len)
{
unsigned int i;
char *result;
result = strdup("progname");
for (i = 0; i < len; i++) {
result = append(result, " ");
result = append(result, escape_windows_command_arg(args[i]));
}
return utf8_to_wchar(result);
}
static int arrays_equal(const char **a, unsigned int alen, const char **b, unsigned int blen)
{
unsigned int i;
if (alen != blen)
return 0;
for (i = 0; i < alen; i++) {
if (strcmp(a[i], b[i]) != 0)
return 0;
}
return 1;
}
static char *format_array(const char **args, unsigned int len)
{
char *result;
unsigned int i;
result = strdup("");
result = append(result, "{");
for (i = 0; i < len; i++) {
if (i > 0)
result = append(result, ", ");
result = append(result, "[");
result = append(result, args[i]);
result = append(result, "]");
}
result = append(result, "}");
return result;
}
static int run_test(const char *args[])
{
LPWSTR *argvw;
char **result;
int args_len, argvw_len, result_len;
args_len = nullarray_length(args);
argvw = CommandLineToArgvW(build_commandline(args, args_len), &argvw_len);
/* Account for added argv[0] in argvw. */
result = wchar_to_utf8_array(argvw+1, argvw_len-1);
result_len = argvw_len - 1;
if (arrays_equal((const char **) result, result_len, args, args_len)) {
printf("PASS %s\n", format_array(args, args_len));
return 1;
} else {
printf("FAIL got %s\n", format_array((const char **) result, result_len));
printf("expected %s\n", format_array(args, args_len));
return 0;
}
}
int main(int argc, char *argv[])
{
unsigned int num_tests, num_passed;
unsigned int i;
num_tests = 0;
num_passed = 0;
for (i = 0; i < sizeof(TESTS) / sizeof(*TESTS); i++) {
num_tests++;
if (run_test(TESTS[i]))
num_passed++;
}
printf("%ld / %ld tests passed.\n", num_passed, num_tests);
return num_passed == num_tests ? 0 : 1;
}