Skip to content
This repository was archived by the owner on Jan 26, 2026. It is now read-only.

Commit ae68f13

Browse files
ansasakicryptomilk
authored andcommitted
misc: Add a function to encode newlines
Given a string, the added function encodes existing newline characters ('\n') as the string "\\n" and puts into a given output buffer. The output buffer must have at least 2 times the length of the input string plus 1 for the terminating '\0'. In the worst case, each character can be replaced by 2 characters. Fixes T189 Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org> Reviewed-by: Jakub Jelen <jjelen@redhat.com> (cherry picked from commit c9ce8fa)
1 parent ad49f0a commit ae68f13

3 files changed

Lines changed: 63 additions & 0 deletions

File tree

include/libssh/misc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,6 @@ void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len);
9595
int ssh_mkdirs(const char *pathname, mode_t mode);
9696

9797
int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
98+
int ssh_newline_vis(const char *string, char *buf, size_t buf_len);
9899

99100
#endif /* MISC_H_ */

src/misc.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,4 +1692,47 @@ int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len)
16921692
return SSH_ERROR;
16931693
}
16941694

1695+
/**
1696+
* @internal
1697+
*
1698+
* @brief Given a string, encode existing newlines as the string "\\n"
1699+
*
1700+
* @param[in] string Input string
1701+
* @param[out] buf Output buffer. This buffer must be at least (2 *
1702+
* strlen(string)) + 1 long. In the worst case,
1703+
* each character can be encoded as 2 characters plus the
1704+
* terminating '\0'.
1705+
* @param[in] buf_len Size of the provided output buffer
1706+
*
1707+
* @returns SSH_ERROR on error; length of the resulting string not counting the
1708+
* terminating '\0' otherwise
1709+
*/
1710+
int ssh_newline_vis(const char *string, char *buf, size_t buf_len)
1711+
{
1712+
const char *in = NULL;
1713+
char *out = NULL;
1714+
1715+
if (string == NULL || buf == NULL || buf_len == 0) {
1716+
return SSH_ERROR;
1717+
}
1718+
1719+
if ((2 * strlen(string) + 1) > buf_len) {
1720+
SSH_LOG(SSH_LOG_WARNING, "Buffer too small");
1721+
return SSH_ERROR;
1722+
}
1723+
1724+
out = buf;
1725+
for (in = string; *in != '\0'; in++) {
1726+
if (*in == '\n') {
1727+
*out++ = '\\';
1728+
*out++ = 'n';
1729+
} else {
1730+
*out++ = *in;
1731+
}
1732+
}
1733+
*out = '\0';
1734+
1735+
return out - buf;
1736+
}
1737+
16951738
/** @} */

tests/unittests/torture_misc.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,24 @@ static void torture_ssh_quote_file_name(UNUSED_PARAM(void **state))
637637
assert_int_equal(rc, SSH_ERROR);
638638
}
639639

640+
static void torture_ssh_newline_vis(UNUSED_PARAM(void **state))
641+
{
642+
int rc;
643+
char buffer[1024];
644+
645+
rc = ssh_newline_vis("\n", buffer, 1024);
646+
assert_int_equal(rc, 2);
647+
assert_string_equal(buffer, "\\n");
648+
649+
rc = ssh_newline_vis("\n\n\n\n", buffer, 1024);
650+
assert_int_equal(rc, 8);
651+
assert_string_equal(buffer, "\\n\\n\\n\\n");
652+
653+
rc = ssh_newline_vis("a\nb\n", buffer, 1024);
654+
assert_int_equal(rc, 6);
655+
assert_string_equal(buffer, "a\\nb\\n");
656+
}
657+
640658
int torture_run_tests(void) {
641659
int rc;
642660
struct CMUnitTest tests[] = {
@@ -656,6 +674,7 @@ int torture_run_tests(void) {
656674
cmocka_unit_test(torture_timeout_update),
657675
cmocka_unit_test(torture_ssh_analyze_banner),
658676
cmocka_unit_test(torture_ssh_dir_writeable),
677+
cmocka_unit_test(torture_ssh_newline_vis),
659678
cmocka_unit_test(torture_ssh_mkdirs),
660679
cmocka_unit_test(torture_ssh_quote_file_name),
661680
};

0 commit comments

Comments
 (0)