<p>Neels Hofmeyr has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13573">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add osmo_{escape,quote}_str_buf2() for OSMO_STRBUF_APPEND() use<br><br>To be able to append an escaped or quoted string using OSMO_STRBUF_APPEND(),<br>the function signature must be like snprintf: buf and size are first arguments,<br>return value is characters-that-would-be-written.<br><br>Add osmo_escape_str_buf2() and osmo_quote_str_buf2() to match this signature.<br><br>To avoid code duplication, implement osmo_quote_str_buf() and<br>osmo_escape_str_buf() by calling the new functions.<br><br>I decided to allow slight changes to the behavior for current osmo_escape_str()<br>and osmo_escape_str_buf(), because impact on callers is minimal:<br><br>(1) The new implementation uses OSMO_STRBUF_*, and in consequence<br>osmo_quote_str() no longer prints an ending double quote after truncated<br>strings; Before, a truncated output was, sic:<br>  "this string is trunca"<br>and now this becomes, sic:<br>  "this string is truncat<br>I decided to not keep the old behavior because it is questionable to begin<br>with. It looks like the string actually ended at the truncation boundary<br>instead of the reason being not enough space in the output buffer.<br><br>(2) The new osmo_escape_str_buf2() function obviously cannot pass-thru an<br>unchanged char* if no escaping was needed. Sacrifice this tiny optimization<br>feature to avoid code duplication:<br>- it is an unnoticeable optimization,<br>- the caller anyway always passes a string buffer,<br>- the feature caused handling strings and buffers differently depending on<br>  their content (i.e. code that usually writes out strings in full length<br>  "suddenly" truncates because a non-printable character is contained, etc.)<br>I considered adding a skip_if_unescaped flag to the osmo_quote_str_buf2()<br>function signature, but in the end decided that the API clutter is not worth<br>having for all the above reasons.<br><br>Adjust tests to accomodate above changes.<br><br>Change-Id: Id748b906b0083b1f1887f2be7a53cae705a8a9ae<br>---<br>M TODO-RELEASE<br>M include/osmocom/core/utils.h<br>M src/utils.c<br>M tests/utils/utils_test.c<br>M tests/utils/utils_test.ok<br>5 files changed, 110 insertions(+), 44 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/73/13573/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/TODO-RELEASE b/TODO-RELEASE</span><br><span>index 5ddc57a..7c81e32 100644</span><br><span>--- a/TODO-RELEASE</span><br><span>+++ b/TODO-RELEASE</span><br><span>@@ -11,3 +11,11 @@</span><br><span> libosmogb       gprs_nsvc               Adding sig_weight and data_weight members for IP-SNS support</span><br><span> libosmogb       various new symbols     Adding functions related to IP-SNS support</span><br><span> libosmocore       osmo_fsm_inst           Add flag proc.terminating (ABI change)</span><br><span style="color: hsl(120, 100%, 40%);">+libosmocore     osmo_escape_str(),      These now always copy to the buffer instead of returning the</span><br><span style="color: hsl(120, 100%, 40%);">+          osmo_escape_str_buf()     unchanged input string when no chars needed escaping, hence</span><br><span style="color: hsl(120, 100%, 40%);">+                                   returned strings might now also be truncated even if all chars were printable.</span><br><span style="color: hsl(120, 100%, 40%);">+libosmocore   osmo_escape_str_buf2()  New function signature similar to snprintf(), for use with OSMO_STRBUF_APPEND().</span><br><span style="color: hsl(120, 100%, 40%);">+libosmocore   osmo_quote_str(),       On string truncation, these used to print a closing quote '"' after the</span><br><span style="color: hsl(120, 100%, 40%);">+          osmo_quote_str_buf()      truncated string. This is no longer the case. e.g. a string 'truncated' in a</span><br><span style="color: hsl(120, 100%, 40%);">+                                          9-char buffer used to print '"trunca"\0', which now becomes '"truncat\0'.</span><br><span style="color: hsl(120, 100%, 40%);">+libosmocore osmo_quote_str_buf2()   New function signature similar to snprintf(), for use with OSMO_STRBUF_APPEND().</span><br><span>diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h</span><br><span>index e19649a..ecb04b5 100644</span><br><span>--- a/include/osmocom/core/utils.h</span><br><span>+++ b/include/osmocom/core/utils.h</span><br><span>@@ -138,9 +138,11 @@</span><br><span> bool osmo_separated_identifiers_valid(const char *str, const char *sep_chars);</span><br><span> </span><br><span> const char *osmo_escape_str(const char *str, int len);</span><br><span style="color: hsl(0, 100%, 40%);">-char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_escape_str_buf2(char *buf, size_t bufsize, const char *str, int in_len);</span><br><span> const char *osmo_quote_str(const char *str, int in_len);</span><br><span style="color: hsl(0, 100%, 40%);">-char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_quote_str_buf2(char *buf, size_t bufsize, const char *str, int in_len);</span><br><span> </span><br><span> uint32_t osmo_isqrt32(uint32_t x);</span><br><span> </span><br><span>diff --git a/src/utils.c b/src/utils.c</span><br><span>index b50ceab..7def0b8 100644</span><br><span>--- a/src/utils.c</span><br><span>+++ b/src/utils.c</span><br><span>@@ -557,22 +557,74 @@</span><br><span>  * \param[inout] buf  string buffer to write escaped characters to.</span><br><span>  * \param[in] bufsize  size of \a buf.</span><br><span>  * \returns buf containing an escaped representation, possibly truncated.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns buf containing an escaped representation, possibly truncated,</span><br><span style="color: hsl(120, 100%, 40%);">+ *          or "(null)" if str == NULL, or "(error)" in case of errors.</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize)</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  int in_pos = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- int next_unprintable = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-       int out_pos = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-        char *out = buf;</span><br><span style="color: hsl(0, 100%, 40%);">-        /* -1 to leave space for a final \0 */</span><br><span style="color: hsl(0, 100%, 40%);">-  int out_len = bufsize-1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span>      if (!str)</span><br><span>            return "(null)";</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        rc = osmo_escape_str_buf2(buf, bufsize, str, in_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!buf || rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return "(error)";</span><br><span style="color: hsl(120, 100%, 40%);">+   return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Copy N characters to a buffer with a function signature useful for OSMO_STRBUF_APPEND().</span><br><span style="color: hsl(120, 100%, 40%);">+ * Similarly to snprintf(), the result is always nul terminated (except if buf is NULL or bufsize is 0).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] buf  Target buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] bufsize  sizeof(buf).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] str  String to copy.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] n  Maximum number of non-nul characters to copy.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Number of characters that would be written if bufsize were large enough excluding '\0' (like snprintf()).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_print_n(char *buf, size_t bufsize, const char *str, size_t n)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   size_t write_n;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!str)</span><br><span style="color: hsl(120, 100%, 40%);">+             str = "";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ n = strnlen(str, n);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!buf || !bufsize)</span><br><span style="color: hsl(120, 100%, 40%);">+         return n;</span><br><span style="color: hsl(120, 100%, 40%);">+     write_n = n;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (write_n >= bufsize)</span><br><span style="color: hsl(120, 100%, 40%);">+            write_n = bufsize - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (write_n)</span><br><span style="color: hsl(120, 100%, 40%);">+          strncpy(buf, str, write_n);</span><br><span style="color: hsl(120, 100%, 40%);">+   buf[write_n] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return n;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return the string with all non-printable characters escaped.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The function signature is suitable for OSMO_STRBUF_APPEND().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] buf  string buffer to write escaped characters to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] bufsize  sizeof(buf).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] str  A string that may contain any characters.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] in_len  Pass -1 to print until nul char, or >= 0 to force a length (also past nul chars).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Number of characters that would be written if bufsize were large enough excluding '\0' (like snprintf()).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_escape_str_buf2(char *buf, size_t bufsize, const char *str, int in_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_strbuf sb = { .buf = buf, .len = bufsize };</span><br><span style="color: hsl(120, 100%, 40%);">+       int in_pos = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       int next_unprintable = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!str)</span><br><span style="color: hsl(120, 100%, 40%);">+             in_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        if (in_len < 0)</span><br><span>           in_len = strlen(str);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+     /* Make sure of '\0' termination */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!in_len)</span><br><span style="color: hsl(120, 100%, 40%);">+          OSMO_STRBUF_PRINTF(sb, "%s", "");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      while (in_pos < in_len) {</span><br><span>                 for (next_unprintable = in_pos;</span><br><span>                   next_unprintable < in_len && isprint((int)str[next_unprintable])</span><br><span>@@ -580,24 +632,16 @@</span><br><span>                  && str[next_unprintable] != '\\';</span><br><span>                    next_unprintable++);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (next_unprintable == in_len && in_pos == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        osmo_strlcpy(buf, str, bufsize);</span><br><span style="color: hsl(0, 100%, 40%);">-                        return buf;</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(120, 100%, 40%);">+             OSMO_STRBUF_APPEND(sb, osmo_print_n, &str[in_pos], next_unprintable - in_pos);</span><br><span style="color: hsl(120, 100%, 40%);">+            in_pos = next_unprintable;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          while (in_pos < next_unprintable && out_pos < out_len)</span><br><span style="color: hsl(0, 100%, 40%);">-                    out[out_pos++] = str[in_pos++];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         if (out_pos == out_len || in_pos == in_len)</span><br><span style="color: hsl(120, 100%, 40%);">+           if (in_pos == in_len)</span><br><span>                        goto done;</span><br><span> </span><br><span>               switch (str[next_unprintable]) {</span><br><span> #define BACKSLASH_CASE(c, repr) \</span><br><span>                case c: \</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (out_pos > out_len-2) \</span><br><span style="color: hsl(0, 100%, 40%);">-                           goto done; \</span><br><span style="color: hsl(0, 100%, 40%);">-                    out[out_pos++] = '\\'; \</span><br><span style="color: hsl(0, 100%, 40%);">-                        out[out_pos++] = repr; \</span><br><span style="color: hsl(120, 100%, 40%);">+                      OSMO_STRBUF_PRINTF(sb, "\\%c", repr); \</span><br><span>                    break</span><br><span> </span><br><span>            BACKSLASH_CASE('\n', 'n');</span><br><span>@@ -613,19 +657,14 @@</span><br><span> #undef BACKSLASH_CASE</span><br><span> </span><br><span>              default:</span><br><span style="color: hsl(0, 100%, 40%);">-                        out_pos += snprintf(&out[out_pos], out_len - out_pos, "\\%u", (unsigned char)str[in_pos]);</span><br><span style="color: hsl(0, 100%, 40%);">-                        if (out_pos > out_len) {</span><br><span style="color: hsl(0, 100%, 40%);">-                             out_pos = out_len;</span><br><span style="color: hsl(0, 100%, 40%);">-                              goto done;</span><br><span style="color: hsl(0, 100%, 40%);">-                      }</span><br><span style="color: hsl(120, 100%, 40%);">+                     OSMO_STRBUF_PRINTF(sb, "\\%u", (unsigned char)str[in_pos]);</span><br><span>                        break;</span><br><span>               }</span><br><span>            in_pos ++;</span><br><span>   }</span><br><span> </span><br><span> done:</span><br><span style="color: hsl(0, 100%, 40%);">-  out[out_pos] = '\0';</span><br><span style="color: hsl(0, 100%, 40%);">-    return out;</span><br><span style="color: hsl(120, 100%, 40%);">+   return sb.chars_needed;</span><br><span> }</span><br><span> </span><br><span> /*! Return the string with all non-printable characters escaped.</span><br><span>@@ -639,24 +678,41 @@</span><br><span>         return osmo_escape_str_buf(str, in_len, namebuf, sizeof(namebuf));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Like osmo_escape_str_buf2(), but returns double-quotes around a string, or "NULL" for a NULL string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * This allows passing any char* value and get its C representation as string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The function signature is suitable for OSMO_STRBUF_APPEND().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] buf  string buffer to write escaped characters to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] bufsize  sizeof(buf).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] str  A string that may contain any characters.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] in_len  Pass -1 to print until nul char, or >= 0 to force a length.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Number of characters that would be written if bufsize were large enough excluding '\0' (like snprintf()).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_quote_str_buf2(char *buf, size_t bufsize, const char *str, int in_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_strbuf sb = { .buf = buf, .len = bufsize };</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!str)</span><br><span style="color: hsl(120, 100%, 40%);">+             OSMO_STRBUF_PRINTF(sb, "NULL");</span><br><span style="color: hsl(120, 100%, 40%);">+     else {</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_STRBUF_PRINTF(sb, "\"");</span><br><span style="color: hsl(120, 100%, 40%);">+          OSMO_STRBUF_APPEND(sb, osmo_escape_str_buf2, str, in_len);</span><br><span style="color: hsl(120, 100%, 40%);">+            OSMO_STRBUF_PRINTF(sb, "\"");</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     return sb.chars_needed;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Like osmo_escape_str(), but returns double-quotes around a string, or "NULL" for a NULL string.</span><br><span>  * This allows passing any char* value and get its C representation as string.</span><br><span>  * \param[in] str  A string that may contain any characters.</span><br><span>  * \param[in] in_len  Pass -1 to print until nul char, or >= 0 to force a length.</span><br><span>  * \returns buf containing a quoted and escaped representation, possibly truncated.</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize)</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      int l;</span><br><span>       if (!str)</span><br><span>            return "NULL";</span><br><span style="color: hsl(0, 100%, 40%);">-        if (bufsize < 3)</span><br><span style="color: hsl(0, 100%, 40%);">-             return "<buf-too-small>";</span><br><span style="color: hsl(0, 100%, 40%);">-       buf[0] = '"';</span><br><span style="color: hsl(0, 100%, 40%);">-      osmo_escape_str_buf(str, in_len, buf + 1, bufsize - 2);</span><br><span style="color: hsl(0, 100%, 40%);">- l = strlen(buf);</span><br><span style="color: hsl(0, 100%, 40%);">-        buf[l] = '"';</span><br><span style="color: hsl(0, 100%, 40%);">-      buf[l+1] = '\0'; /* both osmo_escape_str_buf() and max_len above ensure room for '\0' */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!buf || !bufsize)</span><br><span style="color: hsl(120, 100%, 40%);">+         return "(error)";</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_quote_str_buf2(buf, bufsize, str, in_len);</span><br><span>      return buf;</span><br><span> }</span><br><span> </span><br><span>diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c</span><br><span>index 211b4d1..d27cdf5 100644</span><br><span>--- a/tests/utils/utils_test.c</span><br><span>+++ b/tests/utils/utils_test.c</span><br><span>@@ -585,7 +585,7 @@</span><br><span> </span><br><span>  printf("- never passthru:\n");</span><br><span>     res = osmo_quote_str(printable, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-    if (res != printable)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(res, printable))</span><br><span>          printf("NOT passed through. '%s'\n", res);</span><br><span>         else</span><br><span>                 printf("passed through unchanged '%s'\n", res);</span><br><span>@@ -596,14 +596,14 @@</span><br><span>    printf("- truncation when too long:\n");</span><br><span>   memset(in_buf, 'x', sizeof(in_buf));</span><br><span>         in_buf[0] = '\a';</span><br><span style="color: hsl(0, 100%, 40%);">-       in_buf[5] = 'E';</span><br><span style="color: hsl(120, 100%, 40%);">+      in_buf[6] = 'E';</span><br><span>     memset(out_buf, 0x7f, sizeof(out_buf));</span><br><span>      printf("'%s'\n", osmo_quote_str_buf((const char *)in_buf, sizeof(in_buf), out_buf, 10));</span><br><span>   OSMO_ASSERT(out_buf[10] == 0x7f);</span><br><span> </span><br><span>        printf("- always truncation, even when no escaping needed:\n");</span><br><span>    memset(in_buf, 'x', sizeof(in_buf));</span><br><span style="color: hsl(0, 100%, 40%);">-    in_buf[6] = 'E'; /* dst has 10, less 2 quotes and nul, leaves 7, i.e. in[6] is last */</span><br><span style="color: hsl(120, 100%, 40%);">+        in_buf[7] = 'E'; /* dst has 10, less 1 quote and nul, leaves 8, i.e. in[7] is last */</span><br><span>        in_buf[20] = '\0';</span><br><span>   memset(out_buf, 0x7f, sizeof(out_buf));</span><br><span>      printf("'%s'\n", osmo_quote_str_buf((const char *)in_buf, -1, out_buf, 10));</span><br><span>diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok</span><br><span>index 5783eb1..e30fc5b 100644</span><br><span>--- a/tests/utils/utils_test.ok</span><br><span>+++ b/tests/utils/utils_test.ok</span><br><span>@@ -258,11 +258,11 @@</span><br><span> - zero length:</span><br><span> '""'</span><br><span> - truncation when too long:</span><br><span style="color: hsl(0, 100%, 40%);">-'"\axxxxE"'</span><br><span style="color: hsl(120, 100%, 40%);">+'"\axxxxxE'</span><br><span> - always truncation, even when no escaping needed:</span><br><span style="color: hsl(0, 100%, 40%);">-'"xxxxxxE"'</span><br><span style="color: hsl(120, 100%, 40%);">+'"xxxxxxxE'</span><br><span> - try to feed too little buf for quoting:</span><br><span style="color: hsl(0, 100%, 40%);">-'<buf-too-small>'</span><br><span style="color: hsl(120, 100%, 40%);">+'"'</span><br><span> - NULL string becomes a "NULL" literal:</span><br><span> 'NULL'</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13573">change 13573</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/13573"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Id748b906b0083b1f1887f2be7a53cae705a8a9ae </div>
<div style="display:none"> Gerrit-Change-Number: 13573 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>