mirror of
https://github.com/linux-msm/qdl.git
synced 2026-10-07 06:29:17 -07:00
The contents.xml provides two different "root path" tags, one with Linux and one with Windows path delimiters. Use the Windows tag to avoid issues related to path traversal. Extend the tests as necessary. Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
195 lines
4.8 KiB
C
195 lines
4.8 KiB
C
// SPDX-License-Identifier: BSD-3-Clause
|
|
#define _FILE_OFFSET_BITS 64
|
|
|
|
#include <errno.h>
|
|
#include <setjmp.h>
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <cmocka.h>
|
|
|
|
#include "pathbuf.h"
|
|
|
|
static void init_path(struct pathbuf *path, const char *s, bool set_len)
|
|
{
|
|
size_t len = strlen(s);
|
|
|
|
assert_true(len < sizeof(path->buf));
|
|
memcpy(path->buf, s, len + 1);
|
|
path->len = set_len ? len : 0;
|
|
}
|
|
|
|
static void assert_dirname(const char *in, const char *out, bool set_len)
|
|
{
|
|
struct pathbuf path;
|
|
|
|
init_path(&path, in, set_len);
|
|
qdl_pathbuf_dirname(&path);
|
|
|
|
assert_string_equal(path.buf, out);
|
|
assert_int_equal(path.len, strlen(out));
|
|
}
|
|
|
|
static void test_dirname_posix_root(void **state)
|
|
{
|
|
(void)state;
|
|
assert_dirname("/", "/", true);
|
|
assert_dirname("/", "/", false);
|
|
}
|
|
|
|
static void test_dirname_posix_absolute(void **state)
|
|
{
|
|
(void)state;
|
|
assert_dirname("/foo", "/", true);
|
|
assert_dirname("/foo/bar", "/foo", true);
|
|
assert_dirname("/foo/bar/", "/foo", true);
|
|
}
|
|
|
|
static void test_dirname_relative(void **state)
|
|
{
|
|
(void)state;
|
|
assert_dirname("foo", "foo", true);
|
|
assert_dirname("foo/bar", "foo", true);
|
|
assert_dirname("foo/bar/", "foo", true);
|
|
}
|
|
|
|
static void test_reset_and_dup(void **state)
|
|
{
|
|
struct pathbuf src;
|
|
struct pathbuf dst;
|
|
|
|
(void)state;
|
|
|
|
init_path(&src, "/tmp/example", true);
|
|
qdl_pathbuf_dup(&dst, &src);
|
|
assert_string_equal(dst.buf, src.buf);
|
|
assert_int_equal(dst.len, src.len);
|
|
|
|
qdl_pathbuf_reset(&dst);
|
|
assert_string_equal(dst.buf, "");
|
|
assert_int_equal(dst.len, 0);
|
|
|
|
qdl_pathbuf_reset(NULL);
|
|
}
|
|
|
|
static void test_push_basic_behavior(void **state)
|
|
{
|
|
struct pathbuf path = {0};
|
|
int ret;
|
|
|
|
(void)state;
|
|
|
|
ret = qdl_pathbuf_push(&path, "foo");
|
|
assert_int_equal(ret, 0);
|
|
assert_string_equal(path.buf, "foo");
|
|
assert_int_equal(path.len, strlen("foo"));
|
|
|
|
ret = qdl_pathbuf_push(&path, "bar");
|
|
assert_int_equal(ret, 0);
|
|
assert_string_equal(path.buf, "foo/bar");
|
|
assert_int_equal(path.len, strlen("foo/bar"));
|
|
|
|
ret = qdl_pathbuf_push(&path, "");
|
|
assert_int_equal(ret, 0);
|
|
assert_string_equal(path.buf, "foo/bar");
|
|
assert_int_equal(path.len, strlen("foo/bar"));
|
|
|
|
ret = qdl_pathbuf_push(&path, "./baz");
|
|
assert_int_equal(ret, 0);
|
|
assert_string_equal(path.buf, "foo/bar/baz");
|
|
assert_int_equal(path.len, strlen("foo/bar/baz"));
|
|
|
|
#ifdef _WIN32
|
|
ret = qdl_pathbuf_push(&path, ".\\qux");
|
|
assert_int_equal(ret, 0);
|
|
assert_string_equal(path.buf, "foo/bar/baz/qux");
|
|
assert_int_equal(path.len, strlen("foo/bar/baz/qux"));
|
|
|
|
ret = qdl_pathbuf_push(&path, "nested\\leaf");
|
|
assert_int_equal(ret, 0);
|
|
assert_string_equal(path.buf, "foo/bar/baz/qux/nested/leaf");
|
|
assert_int_equal(path.len, strlen("foo/bar/baz/qux/nested/leaf"));
|
|
|
|
ret = qdl_pathbuf_push(&path, "C:/abs");
|
|
assert_int_equal(ret, 0);
|
|
assert_string_equal(path.buf, "C:/abs");
|
|
assert_int_equal(path.len, strlen("C:/abs"));
|
|
#else
|
|
ret = qdl_pathbuf_push(&path, "/abs");
|
|
assert_int_equal(ret, 0);
|
|
assert_string_equal(path.buf, "/abs");
|
|
assert_int_equal(path.len, strlen("/abs"));
|
|
#endif
|
|
}
|
|
|
|
static void test_push_invalid_args(void **state)
|
|
{
|
|
struct pathbuf path = {0};
|
|
|
|
(void)state;
|
|
|
|
assert_int_equal(qdl_pathbuf_push(NULL, "foo"), -EINVAL);
|
|
assert_int_equal(qdl_pathbuf_push(&path, NULL), -EINVAL);
|
|
}
|
|
|
|
static void test_push_overflow_keeps_state(void **state)
|
|
{
|
|
struct pathbuf path = {0};
|
|
char before[PATH_MAX];
|
|
size_t max_prefix_len;
|
|
int ret;
|
|
|
|
(void)state;
|
|
|
|
max_prefix_len = sizeof(path.buf) - 1;
|
|
memset(path.buf, 'a', max_prefix_len);
|
|
path.buf[max_prefix_len] = '\0';
|
|
path.len = max_prefix_len;
|
|
memcpy(before, path.buf, sizeof(before));
|
|
|
|
ret = qdl_pathbuf_push(&path, "b");
|
|
assert_int_equal(ret, -ENAMETOOLONG);
|
|
assert_string_equal(path.buf, before);
|
|
assert_int_equal(path.len, max_prefix_len);
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
static void test_dirname_windows_drive(void **state)
|
|
{
|
|
(void)state;
|
|
assert_dirname("C:\\", "C:\\", true);
|
|
assert_dirname("C:\\foo", "C:\\", true);
|
|
assert_dirname("C:\\foo\\bar", "C:\\foo", true);
|
|
assert_dirname("C:/foo/bar", "C:/foo", true);
|
|
}
|
|
|
|
static void test_dirname_windows_unc(void **state)
|
|
{
|
|
(void)state;
|
|
assert_dirname("\\\\server\\share", "\\\\server\\share", true);
|
|
assert_dirname("\\\\server\\share\\dir", "\\\\server\\share", true);
|
|
assert_dirname("\\\\server\\share\\dir\\sub", "\\\\server\\share\\dir", true);
|
|
}
|
|
#endif
|
|
|
|
int main(void)
|
|
{
|
|
const struct CMUnitTest tests[] = {
|
|
cmocka_unit_test(test_dirname_posix_root),
|
|
cmocka_unit_test(test_dirname_posix_absolute),
|
|
cmocka_unit_test(test_dirname_relative),
|
|
cmocka_unit_test(test_reset_and_dup),
|
|
cmocka_unit_test(test_push_basic_behavior),
|
|
cmocka_unit_test(test_push_invalid_args),
|
|
cmocka_unit_test(test_push_overflow_keeps_state),
|
|
#ifdef _WIN32
|
|
cmocka_unit_test(test_dirname_windows_drive),
|
|
cmocka_unit_test(test_dirname_windows_unc),
|
|
#endif
|
|
};
|
|
|
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
}
|