aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/misc.h1
-rw-r--r--src/misc.c43
-rw-r--r--tests/unittests/torture_misc.c19
3 files changed, 63 insertions, 0 deletions
diff --git a/include/libssh/misc.h b/include/libssh/misc.h
index 4f0b9439..3cc3b113 100644
--- a/include/libssh/misc.h
+++ b/include/libssh/misc.h
@@ -95,5 +95,6 @@ void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len);
int ssh_mkdirs(const char *pathname, mode_t mode);
int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
+int ssh_newline_vis(const char *string, char *buf, size_t buf_len);
#endif /* MISC_H_ */
diff --git a/src/misc.c b/src/misc.c
index bfdf2820..0f1a7d49 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1692,4 +1692,47 @@ error:
return SSH_ERROR;
}
+/**
+ * @internal
+ *
+ * @brief Given a string, encode existing newlines as the string "\\n"
+ *
+ * @param[in] string Input string
+ * @param[out] buf Output buffer. This buffer must be at least (2 *
+ * strlen(string)) + 1 long. In the worst case,
+ * each character can be encoded as 2 characters plus the
+ * terminating '\0'.
+ * @param[in] buf_len Size of the provided output buffer
+ *
+ * @returns SSH_ERROR on error; length of the resulting string not counting the
+ * terminating '\0' otherwise
+ */
+int ssh_newline_vis(const char *string, char *buf, size_t buf_len)
+{
+ const char *in = NULL;
+ char *out = NULL;
+
+ if (string == NULL || buf == NULL || buf_len == 0) {
+ return SSH_ERROR;
+ }
+
+ if ((2 * strlen(string) + 1) > buf_len) {
+ SSH_LOG(SSH_LOG_WARNING, "Buffer too small");
+ return SSH_ERROR;
+ }
+
+ out = buf;
+ for (in = string; *in != '\0'; in++) {
+ if (*in == '\n') {
+ *out++ = '\\';
+ *out++ = 'n';
+ } else {
+ *out++ = *in;
+ }
+ }
+ *out = '\0';
+
+ return out - buf;
+}
+
/** @} */
diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c
index eff93532..ef06d65f 100644
--- a/tests/unittests/torture_misc.c
+++ b/tests/unittests/torture_misc.c
@@ -637,6 +637,24 @@ static void torture_ssh_quote_file_name(UNUSED_PARAM(void **state))
assert_int_equal(rc, SSH_ERROR);
}
+static void torture_ssh_newline_vis(UNUSED_PARAM(void **state))
+{
+ int rc;
+ char buffer[1024];
+
+ rc = ssh_newline_vis("\n", buffer, 1024);
+ assert_int_equal(rc, 2);
+ assert_string_equal(buffer, "\\n");
+
+ rc = ssh_newline_vis("\n\n\n\n", buffer, 1024);
+ assert_int_equal(rc, 8);
+ assert_string_equal(buffer, "\\n\\n\\n\\n");
+
+ rc = ssh_newline_vis("a\nb\n", buffer, 1024);
+ assert_int_equal(rc, 6);
+ assert_string_equal(buffer, "a\\nb\\n");
+}
+
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
@@ -656,6 +674,7 @@ int torture_run_tests(void) {
cmocka_unit_test(torture_timeout_update),
cmocka_unit_test(torture_ssh_analyze_banner),
cmocka_unit_test(torture_ssh_dir_writeable),
+ cmocka_unit_test(torture_ssh_newline_vis),
cmocka_unit_test(torture_ssh_mkdirs),
cmocka_unit_test(torture_ssh_quote_file_name),
};