logd: log_strtok_r deal with nuls

Rename to log_strntok_r and change from dealing with strings
to dealing with a string and an associated length.

Bug: 23517551
Change-Id: Ia72f1305a53f55eeef9861ac378fb8205fd2378e
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 0965ffd..f0b18da 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -39,14 +39,15 @@
 // Parsing is hard
 
 // called if we see a '<', s is the next character, returns pointer after '>'
-static char *is_prio(char *s) {
-    if (!isdigit(*s++)) {
+static char *is_prio(char *s, size_t len) {
+    if (!len || !isdigit(*s++)) {
         return NULL;
     }
-    static const size_t max_prio_len = 4;
-    size_t len = 0;
+    --len;
+    static const size_t max_prio_len = (len < 4) ? len : 4;
+    size_t priolen = 0;
     char c;
-    while (((c = *s++)) && (++len <= max_prio_len)) {
+    while (((c = *s++)) && (++priolen <= max_prio_len)) {
         if (!isdigit(c)) {
             return ((c == '>') && (*s == '[')) ? s : NULL;
         }
@@ -55,16 +56,19 @@
 }
 
 // called if we see a '[', s is the next character, returns pointer after ']'
-static char *is_timestamp(char *s) {
-    while (*s == ' ') {
+static char *is_timestamp(char *s, size_t len) {
+    while (len && (*s == ' ')) {
         ++s;
+        --len;
     }
-    if (!isdigit(*s++)) {
+    if (!len || !isdigit(*s++)) {
         return NULL;
     }
+    --len;
     bool first_period = true;
     char c;
-    while ((c = *s++)) {
+    while (len && ((c = *s++))) {
+        --len;
         if ((c == '.') && first_period) {
             first_period = false;
         } else if (!isdigit(c)) {
@@ -85,7 +89,11 @@
 // space is one more than <digit> of 9
 #define OPEN_BRACKET_SPACE ((char)(OPEN_BRACKET_SIG | 10))
 
-char *log_strtok_r(char *s, char **last) {
+char *log_strntok_r(char *s, size_t *len, char **last, size_t *sublen) {
+    *sublen = 0;
+    if (!*len) {
+        return NULL;
+    }
     if (!s) {
         if (!(s = *last)) {
             return NULL;
@@ -95,6 +103,7 @@
         if ((*s & SIGNATURE_MASK) == LESS_THAN_SIG) {
             *s = (*s & ~SIGNATURE_MASK) + '0';
             *--s = '<';
+            ++*len;
         }
         // fixup for log signature split [,
         // OPEN_BRACKET_SPACE is space, OPEN_BRACKET_SIG + <digit>
@@ -105,24 +114,30 @@
                 *s = (*s & ~SIGNATURE_MASK) + '0';
             }
             *--s = '[';
+            ++*len;
         }
     }
 
-    s += strspn(s, "\r\n");
+    while (*len && ((*s == '\r') || (*s == '\n'))) {
+        ++s;
+        --*len;
+    }
 
-    if (!*s) { // no non-delimiter characters
+    if (!*len) {
         *last = NULL;
         return NULL;
     }
     char *peek, *tok = s;
 
     for (;;) {
-        char c = *s++;
-        switch (c) {
-        case '\0':
+        if (*len == 0) {
             *last = NULL;
             return tok;
-
+        }
+        char c = *s++;
+        --*len;
+        size_t adjust;
+        switch (c) {
         case '\r':
         case '\n':
             s[-1] = '\0';
@@ -130,7 +145,7 @@
             return tok;
 
         case '<':
-            peek = is_prio(s);
+            peek = is_prio(s, *len);
             if (!peek) {
                 break;
             }
@@ -141,14 +156,26 @@
                 *last = s;
                 return tok;
             }
+            adjust = peek - s;
+            if (adjust > *len) {
+                adjust = *len;
+            }
+            *sublen += adjust;
+            *len -= adjust;
             s = peek;
-            if ((*s == '[') && ((peek = is_timestamp(s + 1)))) {
+            if ((*s == '[') && ((peek = is_timestamp(s + 1, *len - 1)))) {
+                adjust = peek - s;
+                if (adjust > *len) {
+                    adjust = *len;
+                }
+                *sublen += adjust;
+                *len -= adjust;
                 s = peek;
             }
             break;
 
         case '[':
-            peek = is_timestamp(s);
+            peek = is_timestamp(s, *len);
             if (!peek) {
                 break;
             }
@@ -163,9 +190,16 @@
                 *last = s;
                 return tok;
             }
+            adjust = peek - s;
+            if (adjust > *len) {
+                adjust = *len;
+            }
+            *sublen += adjust;
+            *len -= adjust;
             s = peek;
             break;
         }
+        ++*sublen;
     }
     // NOTREACHED
 }
@@ -212,13 +246,13 @@
         bool full = len == (sizeof(buffer) - 1);
         char *ep = buffer + len;
         *ep = '\0';
-        len = 0;
+        size_t sublen;
         for(char *ptr = NULL, *tok = buffer;
-                ((tok = log_strtok_r(tok, &ptr)));
+                ((tok = log_strntok_r(tok, &len, &ptr, &sublen)));
                 tok = NULL) {
-            if (((tok + strlen(tok)) == ep) && (retval != 0) && full) {
-                len = strlen(tok);
-                memmove(buffer, tok, len);
+            if (((tok + sublen) >= ep) && (retval != 0) && full) {
+                memmove(buffer, tok, sublen);
+                len = sublen;
                 break;
             }
             if (*tok) {