Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea1a2411 authored by Mark Salyzyn's avatar Mark Salyzyn
Browse files

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
parent faa92e99
Loading
Loading
Loading
Loading
+58 −24
Original line number Diff line number Diff line
@@ -39,14 +39,15 @@ static const char priority_message[] = { KMSG_PRIORITY(LOG_INFO), '\0' };
// 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 @@ static char *is_prio(char *s) {
}

// 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 @@ static char *is_timestamp(char *s) {
// 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 @@ char *log_strtok_r(char *s, char **last) {
        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 @@ char *log_strtok_r(char *s, char **last) {
                *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 @@ char *log_strtok_r(char *s, char **last) {
            return tok;

        case '<':
            peek = is_prio(s);
            peek = is_prio(s, *len);
            if (!peek) {
                break;
            }
@@ -141,14 +156,26 @@ char *log_strtok_r(char *s, char **last) {
                *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 @@ char *log_strtok_r(char *s, char **last) {
                *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 LogKlog::onDataAvailable(SocketClient *cli) {
        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) {
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@
#include <log/log_read.h>
#include "LogReader.h"

char *log_strtok_r(char *str, char **saveptr);
char *log_strntok_r(char *s, size_t *len, char **saveptr, size_t *sublen);

class LogKlog : public SocketListener {
    LogBuffer *logbuf;
+8 −7
Original line number Diff line number Diff line
@@ -282,30 +282,31 @@ static void readDmesg(LogAudit *al, LogKlog *kl) {
        return;
    }

    int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
    if (len <= 0) {
    int rc = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
    if (rc <= 0) {
        return;
    }

    len += 1024; // Margin for additional input race or trailing nul
    size_t len = rc + 1024; // Margin for additional input race or trailing nul
    std::unique_ptr<char []> buf(new char[len]);

    int rc = klogctl(KLOG_READ_ALL, buf.get(), len);
    rc = klogctl(KLOG_READ_ALL, buf.get(), len);
    if (rc <= 0) {
        return;
    }

    if (rc < len) {
    if ((size_t)rc < len) {
        len = rc + 1;
    }
    buf[len - 1] = '\0';
    buf[--len] = '\0';

    if (kl) {
        kl->synchronize(buf.get());
    }

    size_t sublen;
    for (char *ptr = NULL, *tok = buf.get();
         (rc >= 0) && ((tok = log_strtok_r(tok, &ptr)));
         (rc >= 0) && ((tok = log_strntok_r(tok, &len, &ptr, &sublen)));
         tok = NULL) {
        if (al) {
            rc = al->log(tok);