Do not encode newline characters for abort/log.

The isprint call will return false for chars such as newlines, which
means that the values '\n' and '\t' get encoded which was not the
intent of encodeding the abort and log messages. Add two oct_encode
versions, one that encodes all non-ascii values and only non-printable
ascii values for abort and log data. The other encoding function encodes
all chars that fail isprint() which is used for extra crash data.

Add new unit tests to verify that characters like newlines are not
encoded in the right places.

Bug: 381259755

Test: All unit tests pass.
Change-Id: I682f10e13a2e80ddfa7e87dfdf8181342eb22374
diff --git a/debuggerd/libdebuggerd/utility_host.cpp b/debuggerd/libdebuggerd/utility_host.cpp
index 4efa03c..d87f4fb 100644
--- a/debuggerd/libdebuggerd/utility_host.cpp
+++ b/debuggerd/libdebuggerd/utility_host.cpp
@@ -16,6 +16,7 @@
 
 #include "libdebuggerd/utility_host.h"
 
+#include <ctype.h>
 #include <sys/prctl.h>
 
 #include <charconv>
@@ -102,23 +103,31 @@
   return describe_end(value, desc);
 }
 
-std::string oct_encode(const std::string& data) {
+static std::string oct_encode(const std::string& data, bool (*should_encode_func)(int)) {
   std::string oct_encoded;
   oct_encoded.reserve(data.size());
 
   // N.B. the unsigned here is very important, otherwise e.g. \255 would render as
   // \-123 (and overflow our buffer).
   for (unsigned char c : data) {
-    if (isprint(c)) {
-      oct_encoded += c;
-    } else {
+    if (should_encode_func(c)) {
       std::string oct_digits("\\\0\0\0", 4);
       // char is encodable in 3 oct digits
       static_assert(std::numeric_limits<unsigned char>::max() <= 8 * 8 * 8);
       auto [ptr, ec] = std::to_chars(oct_digits.data() + 1, oct_digits.data() + 4, c, 8);
       oct_digits.resize(ptr - oct_digits.data());
       oct_encoded += oct_digits;
+    } else {
+      oct_encoded += c;
     }
   }
   return oct_encoded;
 }
+
+std::string oct_encode_non_ascii_printable(const std::string& data) {
+  return oct_encode(data, [](int c) { return !isgraph(c) && !isspace(c); });
+}
+
+std::string oct_encode_non_printable(const std::string& data) {
+  return oct_encode(data, [](int c) { return !isprint(c); });
+}