summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2022-09-20 15:08:59 +0900
committerDaiki Ueno <ueno@gnu.org>2023-01-11 16:44:09 +0900
commit1c5f0e2905a1f689a2984cc3b43a05f984aede1a (patch)
tree0f29643bdf6cae5b19ca5a7cd59e48a5c3bc2a6f
parent74bdd762e569861568ccffacd0d6a46676fa79b9 (diff)
downloadgnutls-1c5f0e2905a1f689a2984cc3b43a05f984aede1a.tar.gz
trust: make filesystem path construction flexible
To handle pathnames longer than the fixed length (previously 256), this adds a set of internal API functions around the gnutls_pathbuf_st struct, which enables to safely and efficiently construct pathnames. The new API initially uses the statically allocated buffer and starts allocating memory on heap only after the limit has reached. Signed-off-by: Daiki Ueno <ueno@gnu.org>
-rw-r--r--.gitignore7
-rw-r--r--bootstrap.conf2
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/libgnutls.map5
-rw-r--r--lib/pathbuf.c146
-rw-r--r--lib/pathbuf.h49
-rw-r--r--lib/system.h6
-rw-r--r--lib/system/certs.c43
-rw-r--r--lib/x509/verify-high2.c126
-rw-r--r--tests/Makefile.am6
-rw-r--r--tests/pathbuf.c66
11 files changed, 390 insertions, 68 deletions
diff --git a/.gitignore b/.gitignore
index 288efb9c59..597530a6a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -414,6 +414,7 @@ tests/gnutls-strcodes
tests/gnutls_ext_raw_parse
tests/gnutls_ext_raw_parse_dtls
tests/gnutls_hmac_fast
+tests/gnutls_ktls
tests/gnutls_ocsp_resp_list_import2
tests/gnutls_record_overhead
tests/gnutls_session_set_id
@@ -452,6 +453,7 @@ tests/key-usage-rsa
tests/keygen
tests/keylog-env
tests/keylog-func
+tests/ktls_keyupdate
tests/libpkcs11mock1.la
tests/libpkcs11mock2.la
tests/libutils.la
@@ -545,6 +547,7 @@ tests/openpgp-keyring
tests/openpgpself
tests/openssl
tests/parse_ca
+tests/pathbuf
tests/pathlen/Makefile
tests/pathlen/Makefile.in
tests/pcert-list
@@ -625,6 +628,7 @@ tests/random-art
tests/rawpk-api
tests/record-pad
tests/record-retvals
+tests/record-sendfile
tests/record-sizes
tests/record-sizes-range
tests/record-timeouts
@@ -918,9 +922,6 @@ tests/x509sign-verify-rsa
tests/x509sign-verify2
tests/x509signself
tests/xts-key-check
-tests/gnutls_ktls
-tests/record-sendfile
-tests/ktls_keyupdate
*.tmp
tmp-*
*.trs
diff --git a/bootstrap.conf b/bootstrap.conf
index ad8d7cd51e..c4d1fe06b2 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -27,7 +27,7 @@ required_submodules="tests/suite/tls-fuzzer/python-ecdsa tests/suite/tls-fuzzer/
# Those modules are common to lib/ and src/.
common_modules="
-alloca attribute byteswap c-ctype c-strcase canonicalize-lgpl explicit_bzero fopen-gnu func getline gettext-h gettimeofday hash hash-pjw-bare arpa_inet inet_ntop inet_pton intprops linkedhash-list lock memmem-simple minmax netdb netinet_in read-file secure_getenv setsockopt snprintf stdint stpcpy strcase strdup-posix strndup strtok_r strverscmp sys_socket sys_stat sys_types threadlib time_r tls unistd valgrind-tests vasprintf verify vsnprintf xalloc-oversized
+alloca attribute byteswap c-ctype c-strcase canonicalize-lgpl explicit_bzero fopen-gnu func getline gettext-h gettimeofday hash hash-pjw-bare arpa_inet inet_ntop inet_pton intprops linkedhash-list lock memmem-simple minmax netdb netinet_in pathmax read-file secure_getenv setsockopt snprintf stdint stpcpy strcase strdup-posix strndup strtok_r strverscmp sys_socket sys_stat sys_types threadlib time_r tls unistd valgrind-tests vasprintf verify vsnprintf xalloc-oversized
"
gnulib_modules="
$common_modules dirname-lgpl extensions gendocs havelib ldd lib-msvc-compat lib-symbol-versions maintainer-makefile manywarnings pmccabe2html warnings
diff --git a/lib/Makefile.am b/lib/Makefile.am
index fc83a37333..6d4e8d225a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -83,7 +83,7 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c gthreads.h handshake-tls
cert-session.c handshake-checks.c dtls-sw.c dh-primes.c openpgp_compat.c \
crypto-selftests.c crypto-selftests-pk.c secrets.c extv.c extv.h \
hello_ext_lib.c hello_ext_lib.h ocsp-api.c stek.c cert-cred-rawpk.c \
- iov.c iov.h system/ktls.c system/ktls.h
+ iov.c iov.h system/ktls.c system/ktls.h pathbuf.c pathbuf.h
if ENABLE_GOST
COBJECTS += vko.c
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 31cbb90489..72e425c3a0 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1514,4 +1514,9 @@ GNUTLS_PRIVATE_3_4 {
_gnutls_crypto_register_cipher;
# needed by tests/tls12-rehandshake-cert-ticket
_gnutls_session_ticket_disable_server;
+ # needed by tests/pathbuf
+ _gnutls_pathbuf_init;
+ _gnutls_pathbuf_append;
+ _gnutls_pathbuf_truncate;
+ _gnutls_pathbuf_deinit;
} GNUTLS_3_4;
diff --git a/lib/pathbuf.c b/lib/pathbuf.c
new file mode 100644
index 0000000000..a5d6316fcd
--- /dev/null
+++ b/lib/pathbuf.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2010-2022 Free Software Foundation, Inc.
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * Author: Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ *
+ */
+
+#include "config.h"
+
+#include "pathbuf.h"
+#include "gnutls_int.h"
+#include <limits.h>
+#include "intprops.h"
+
+static int
+pathbuf_reserve(struct gnutls_pathbuf_st *buffer, size_t to_add)
+{
+ size_t len;
+ char *ptr;
+
+ len = buffer->len;
+
+ if (INT_ADD_OVERFLOW(len, to_add)) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ len += to_add;
+
+ /* NUL terminator. */
+ if (INT_ADD_OVERFLOW(len, 1)) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ len++;
+
+ if (len <= buffer->cap) {
+ return 0;
+ }
+
+ if (buffer->ptr == buffer->base) {
+ ptr = gnutls_strdup(buffer->ptr);
+ if (!ptr) {
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ }
+ buffer->ptr = ptr;
+ }
+
+ ptr = gnutls_realloc(buffer->ptr, len);
+ if (!ptr) {
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ }
+
+ buffer->ptr = ptr;
+ buffer->cap = len;
+
+ return 0;
+}
+
+int
+_gnutls_pathbuf_init(struct gnutls_pathbuf_st *buffer, const char *base)
+{
+ size_t len;
+ int ret;
+
+ memset(buffer, 0, sizeof(*buffer));
+ buffer->cap = sizeof(buffer->base);
+ buffer->ptr = buffer->base;
+
+ len = strlen(base);
+
+ ret = pathbuf_reserve(buffer, len);
+ if (ret < 0) {
+ return ret;
+ }
+
+ strcpy(buffer->ptr, base);
+ buffer->len = len;
+
+ return 0;
+}
+
+int
+_gnutls_pathbuf_append(struct gnutls_pathbuf_st *buffer, const char *component)
+{
+ size_t len;
+ char *p;
+ int ret;
+
+ len = strlen(component);
+
+ /* Path separator. */
+ if (INT_ADD_OVERFLOW(len, 1)) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ len++;
+
+ ret = pathbuf_reserve(buffer, len);
+ if (ret < 0) {
+ return ret;
+ }
+
+ p = stpcpy(&buffer->ptr[buffer->len], "/");
+ strcpy(p, component);
+
+ /* Overflow is already checked in the call to pathbuf_reserve
+ * above.
+ */
+ buffer->len += len;
+
+ return 0;
+}
+
+int
+_gnutls_pathbuf_truncate(struct gnutls_pathbuf_st *buffer, size_t len)
+{
+ if (len > buffer->len) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ buffer->len = len;
+ buffer->ptr[len] = '\0';
+ return 0;
+}
+
+void
+_gnutls_pathbuf_deinit(struct gnutls_pathbuf_st *buffer)
+{
+ if (buffer->ptr != buffer->base) {
+ gnutls_free(buffer->ptr);
+ }
+ memset(buffer, 0, sizeof(*buffer));
+}
+
diff --git a/lib/pathbuf.h b/lib/pathbuf.h
new file mode 100644
index 0000000000..2739e4dd29
--- /dev/null
+++ b/lib/pathbuf.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010-2022 Free Software Foundation, Inc.
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * Author: Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef GNUTLS_LIB_PATHBUF_H
+#define GNUTLS_LIB_PATHBUF_H
+
+#include "pathmax.h"
+#define GNUTLS_PATH_MAX PATH_MAX
+
+struct gnutls_pathbuf_st {
+ char base[GNUTLS_PATH_MAX + 1];
+ char *ptr; /* API */
+ size_t len; /* API: NOT including NUL */
+ size_t cap; /* including NUL */
+};
+
+/* Initialize BUFFER with the content BASE. */
+int _gnutls_pathbuf_init(struct gnutls_pathbuf_st *buffer, const char *base);
+
+/* Append COMPONENT to BUFFER, separated with a "/". */
+int _gnutls_pathbuf_append(struct gnutls_pathbuf_st *buffer, const char *component);
+
+/* Truncate the length of BUFFER to LEN. */
+int _gnutls_pathbuf_truncate(struct gnutls_pathbuf_st *buffer, size_t len);
+
+/* Deinitialize BUFFER. */
+void _gnutls_pathbuf_deinit(struct gnutls_pathbuf_st *buffer);
+
+#endif /* GNUTLS_LIB_PATHBUF_H */
diff --git a/lib/system.h b/lib/system.h
index e15c8cd33d..13cbf1a9fe 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -44,11 +44,7 @@ extern CertEnumCRLsInStoreFunc pCertEnumCRLsInStore;
#include <sys/uio.h> /* for writev */
#endif
-#ifdef _POSIX_PATH_MAX
-# define GNUTLS_PATH_MAX _POSIX_PATH_MAX
-#else
-# define GNUTLS_PATH_MAX 256
-#endif
+#include "pathbuf.h"
int system_errno(gnutls_transport_ptr_t);
diff --git a/lib/system/certs.c b/lib/system/certs.c
index c06b82354b..e155bd9389 100644
--- a/lib/system/certs.c
+++ b/lib/system/certs.c
@@ -217,31 +217,42 @@ int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags,
# if defined(ANDROID) || defined(__ANDROID__)
# define DEFAULT_TRUST_STORE_DIR "/system/etc/security/cacerts/"
+# define DEFAULT_REVOCATION_DIR "/data/misc/keychain/cacerts-removed"
+
static int load_revoked_certs(gnutls_x509_trust_list_t list, unsigned type)
{
DIR *dirp;
struct dirent *d;
int ret;
int r = 0;
- char path[GNUTLS_PATH_MAX];
+ struct gnutls_pathbuf_st pathbuf;
- dirp = opendir("/data/misc/keychain/cacerts-removed/");
+ dirp = opendir(DEFAULT_REVOCATION_DIR);
if (dirp != NULL) {
- do {
- d = readdir(dirp);
- if (d != NULL && d->d_type == DT_REG) {
- snprintf(path, sizeof(path),
- "/data/misc/keychain/cacerts-removed/%s",
- d->d_name);
-
- ret =
- gnutls_x509_trust_list_remove_trust_file
- (list, path, type);
- if (ret >= 0)
- r += ret;
- }
+ size_t base_len;
+
+ ret = _gnutls_pathbuf_init(&pathbuf, DEFAULT_REVOCATION_DIR);
+ if (ret < 0) {
+ return 0;
+ }
+
+ base_len = pathbuf.len;
+ while ((d = readdir(dirp)) != NULL) {
+ if (d->d_type != DT_REG) {
+ continue;
+ }
+ ret = _gnutls_pathbuf_append(&pathbuf, d->d_name);
+ if (ret < 0) {
+ continue;
+ }
+ ret = gnutls_x509_trust_list_remove_trust_file
+ (list, pathbuf.ptr, type);
+ if (ret >= 0) {
+ r += ret;
+ }
+ (void)_gnutls_pathbuf_truncate(&pathbuf, base_len);
}
- while (d != NULL);
+ _gnutls_pathbuf_deinit(&pathbuf);
closedir(dirp);
}
diff --git a/lib/x509/verify-high2.c b/lib/x509/verify-high2.c
index eaaaa8b897..e69b1567c4 100644
--- a/lib/x509/verify-high2.c
+++ b/lib/x509/verify-high2.c
@@ -393,7 +393,7 @@ int load_dir_certs(const char *dirname,
{
int ret;
int r = 0;
- char path[GNUTLS_PATH_MAX];
+ struct gnutls_pathbuf_st pathbuf;
#if !defined(_WIN32) || !defined(_UNICODE)
DIR *dirp;
@@ -401,29 +401,44 @@ int load_dir_certs(const char *dirname,
dirp = opendir(dirname);
if (dirp != NULL) {
+ size_t base_len;
+
+ ret = _gnutls_pathbuf_init(&pathbuf, dirname);
+ if (ret < 0) {
+ return r;
+ }
+
+ base_len = pathbuf.len;
while ((d = readdir(dirp)) != NULL) {
#ifdef _DIRENT_HAVE_D_TYPE
- if (d->d_type == DT_REG || d->d_type == DT_LNK || d->d_type == DT_UNKNOWN)
+ switch (d->d_type) {
+ case DT_REG:
+ case DT_LNK:
+ case DT_UNKNOWN:
+ break;
+ default:
+ continue;
+ }
#endif
- {
- snprintf(path, sizeof(path), "%s/%s",
- dirname, d->d_name);
-
- if (crl != 0) {
- ret =
- gnutls_x509_trust_list_add_trust_file
- (list, NULL, path, type, tl_flags,
- tl_vflags);
- } else {
- ret =
- gnutls_x509_trust_list_add_trust_file
- (list, path, NULL, type, tl_flags,
- tl_vflags);
- }
- if (ret >= 0)
- r += ret;
+ ret = _gnutls_pathbuf_append(&pathbuf, d->d_name);
+ if (ret < 0) {
+ continue;
+ }
+ if (crl != 0) {
+ ret = gnutls_x509_trust_list_add_trust_file
+ (list, NULL, pathbuf.ptr, type, tl_flags,
+ tl_vflags);
+ } else {
+ ret = gnutls_x509_trust_list_add_trust_file
+ (list, pathbuf.ptr, NULL, type, tl_flags,
+ tl_vflags);
}
+ if (ret >= 0) {
+ r += ret;
+ }
+ (void)_gnutls_pathbuf_truncate(&pathbuf, base_len);
}
+ _gnutls_pathbuf_deinit(&pathbuf);
closedir(dirp);
}
#else /* _WIN32 */
@@ -432,41 +447,70 @@ int load_dir_certs(const char *dirname,
struct _tdirent *d;
gnutls_datum_t utf16 = {NULL, 0};
+#undef UCS2_ENDIAN
#ifdef WORDS_BIGENDIAN
- r = _gnutls_utf8_to_ucs2(dirname, strlen(dirname), &utf16, 1);
+#define UCS2_ENDIAN 1
#else
- r = _gnutls_utf8_to_ucs2(dirname, strlen(dirname), &utf16, 0);
+#define UCS2_ENDIAN 0
#endif
- if (r < 0)
- return gnutls_assert_val(r);
+
+ ret = _gnutls_utf8_to_ucs2(dirname, strlen(dirname), &utf16, UCS2_ENDIAN);
+ if (ret < 0) {
+ return gnutls_assert_val(ret);
+ }
dirp = _topendir((_TCHAR*)utf16.data);
gnutls_free(utf16.data);
if (dirp != NULL) {
+ size_t base_len;
+
+ ret = _gnutls_pathbuf_init(&pathbuf, dirname);
+ if (ret < 0) {
+ return r;
+ }
+
+ base_len = pathbuf.len;
while ((d = _treaddir(dirp)) != NULL) {
+ gnutls_datum_t utf8 = {NULL, 0};
#ifdef _DIRENT_HAVE_D_TYPE
- if (d->d_type == DT_REG || d->d_type == DT_LNK || d->d_type == DT_UNKNOWN)
+ switch (d->d_type) {
+ case DT_REG:
+ case DT_LNK:
+ case DT_UNKNOWN:
+ break;
+ default:
+ continue;
+ }
#endif
- {
- snprintf(path, sizeof(path), "%s/%ls",
- dirname, d->d_name);
-
- if (crl != 0) {
- ret =
- gnutls_x509_trust_list_add_trust_file
- (list, NULL, path, type, tl_flags,
- tl_vflags);
- } else {
- ret =
- gnutls_x509_trust_list_add_trust_file
- (list, path, NULL, type, tl_flags,
- tl_vflags);
- }
- if (ret >= 0)
- r += ret;
+ ret = _gnutls_ucs2_to_utf8(d->d_name,
+ d->d_namlen * sizeof(d->d_name[0]),
+ &utf8,
+ UCS2_ENDIAN);
+ if (ret < 0) {
+ continue;
+ }
+ ret = _gnutls_pathbuf_append(&pathbuf, utf8.data);
+ gnutls_free(utf8.data);
+ if (ret < 0) {
+ continue;
+ }
+
+ if (crl != 0) {
+ ret = gnutls_x509_trust_list_add_trust_file
+ (list, NULL, pathbuf.ptr, type, tl_flags,
+ tl_vflags);
+ } else {
+ ret = gnutls_x509_trust_list_add_trust_file
+ (list, pathbuf.ptr, NULL, type, tl_flags,
+ tl_vflags);
}
+ if (ret >= 0)
+ r += ret;
+ (void)_gnutls_pathbuf_truncate(&pathbuf, base_len);
}
+ _gnutls_pathbuf_deinit(&pathbuf);
_tclosedir(dirp);
}
+#undef UCS2_ENDIAN
#endif /* _WIN32 */
return r;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 573e911a0b..2872cb1aa5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -234,7 +234,7 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \
x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
x509-upnconstraint xts-key-check cipher-padding pkcs7-verify-double-free \
- fips-rsa-sizes tls12-rehandshake-ticket
+ fips-rsa-sizes tls12-rehandshake-ticket pathbuf
ctests += tls-channel-binding
@@ -480,6 +480,10 @@ buffer_CPPFLAGS = $(AM_CPPFLAGS) \
-I$(top_srcdir)/gl \
-I$(top_builddir)/gl
+pathbuf_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/gl \
+ -I$(top_builddir)/gl
+
if ENABLE_PKCS11
if !WINDOWS
ctests += tls13/post-handshake-with-cert-pkcs11 pkcs11/tls-neg-pkcs11-no-key \
diff --git a/tests/pathbuf.c b/tests/pathbuf.c
new file mode 100644
index 0000000000..f308ac090a
--- /dev/null
+++ b/tests/pathbuf.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * Author: Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+
+#include "../lib/pathbuf.h"
+#include "utils.h"
+#include <string.h>
+#include <assert.h>
+
+static char long_path[GNUTLS_PATH_MAX + 2];
+
+void
+doit(void)
+{
+ struct gnutls_pathbuf_st pathbuf;
+ int i;
+ int ret;
+
+ ret = _gnutls_pathbuf_init(&pathbuf, "./x509certs");
+ assert(ret == 0);
+ assert(strcmp(pathbuf.ptr, "./x509certs") == 0);
+ assert(pathbuf.len == sizeof("./x509certs") - 1);
+
+ ret = _gnutls_pathbuf_append(&pathbuf, "cert.pem");
+ assert(ret == 0);
+ assert(strcmp(pathbuf.ptr, "./x509certs/cert.pem") == 0);
+ assert(pathbuf.len == sizeof("./x509certs/cert.pem") - 1);
+ _gnutls_pathbuf_deinit(&pathbuf);
+
+ for (i = -1; i <= 1; i++) {
+ memset(long_path, 'a', GNUTLS_PATH_MAX + i);
+ long_path[GNUTLS_PATH_MAX + i] = '\0';
+
+ ret = _gnutls_pathbuf_init(&pathbuf, long_path);
+ assert(ret == 0);
+ assert(strcmp(pathbuf.ptr, long_path) == 0);
+ assert(pathbuf.len == (size_t)GNUTLS_PATH_MAX + i);
+
+ ret = _gnutls_pathbuf_append(&pathbuf, "cert.pem");
+ assert(ret == 0);
+ assert(memcmp(pathbuf.ptr, long_path, GNUTLS_PATH_MAX + i) == 0);
+ assert(strcmp(&pathbuf.ptr[GNUTLS_PATH_MAX + i], "/cert.pem") == 0);
+ assert(pathbuf.len == GNUTLS_PATH_MAX + i + sizeof("/cert.pem") - 1);
+ _gnutls_pathbuf_deinit(&pathbuf);
+ }
+}