Example #1
0
/* a special line with instruction pointer may be present in the format
 * RIP: 0010:[<ffffffff811c6ed5>]  [<ffffffff811c6ed5>] __block_write_full_page+0xa5/0x350
 * (for x86_64), or
 * EIP: [<f8e40765>] wdev_priv.part.8+0x3/0x5 [wl] SS:ESP 0068:f180dbf8
 * (for i386, where it is AFTER the trace)
 */
static struct sr_koops_frame*
parse_IP(const char **input)
{
    struct sr_koops_frame *frame;
    const char *local_input = *input;
    sr_skip_char_span(&local_input, " \t");

    if (sr_skip_string(&local_input, "RIP:"))
    {
        if (!sr_skip_char_span(&local_input, " \t"))
            return NULL;

        /* The address is there twice, skip the first one */
        if (!sr_skip_char_cspan(&local_input, " \t"))
            return NULL;

        if (!sr_skip_char_span(&local_input, " \t"))
            return NULL;

        frame = sr_koops_frame_parse(&local_input);
        if (!frame)
            return NULL;
    }
    else if(sr_skip_string(&local_input, "EIP:"))
    {
        if (!sr_skip_char_span(&local_input, " \t"))
            return NULL;

        frame = sr_koops_frame_new();

        if (!sr_koops_parse_address(&local_input, &frame->address))
        {
            sr_koops_frame_free(frame);
            return NULL;
        }

        sr_skip_char_span(&local_input, " \t");

        /* Question mark means unreliable */
        frame->reliable = sr_skip_char(&local_input, '?') != true;

        sr_skip_char_span(&local_input, " \t");

        if (!sr_koops_parse_function(&local_input,
                                     &frame->function_name,
                                     &frame->function_offset,
                                     &frame->function_length,
                                     &frame->module_name))
        {
            sr_koops_frame_free(frame);
            return NULL;
        }
    }
    else
        return NULL;

    sr_skip_char_cspan(&local_input, "\n");
    *input = local_input;
    return frame;
}
Example #2
0
static char *
parse_alt_stack_start(const char **input)
{
    char *stack_label = NULL;
    const char *local_input = *input;
    sr_skip_char_span(&local_input, " \t");

    if (!sr_skip_char(&local_input, '<') ||
        !sr_parse_char_cspan(&local_input, "> \t\n", &stack_label) ||
        !sr_skip_char(&local_input, '>'))
    {
        free(stack_label);
        return NULL;
    }

    *input = local_input;
    return stack_label;
}
Example #3
0
struct sr_ruby_frame *
sr_ruby_frame_parse(const char **input,
                    struct sr_location *location)
{
    const char *local_input = *input;
    struct sr_ruby_frame *frame = sr_ruby_frame_new();

    /* take everything before the backtick
     * /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
     * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     */
    char *filename_lineno_in = NULL;
    if (!sr_parse_char_cspan(&local_input, "`", &filename_lineno_in))
    {
        location->message = sr_strdup("Unable to find the '`' character "
                                      "identifying the beginning of function name.");
        goto fail;
    }

    size_t l = strlen(filename_lineno_in);
    location->column += l;

    char *p = filename_lineno_in + l;

    /* /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
     *                                                           ^^^^
     */
    p -= strlen(":in ");
    if (p < filename_lineno_in || 0 != strcmp(":in ", p))
    {
        location->column -= strlen(":in ");
        location->message = sr_strdup("Unable to find ':in ' preceding the "
                                      "backtick character.");
        goto fail;
    }

    /* Find the beginning of the line number. */
    *p = '\0';
    do {
        p--;
    } while (p >= filename_lineno_in && isdigit(*p));
    p++;

    /* /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
     *                                                         ^^
     */
    char *p_copy = p;
    int lineno_len = sr_parse_uint32((const char **)&p_copy, &frame->file_line);
    if (lineno_len <= 0)
    {
        location->message = sr_strdup("Unable to find line number before ':in '");
        goto fail;
    }

    /* /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
     *                                                        ^
     */
    p--;
    if (p < filename_lineno_in || *p != ':')
    {
        location->column -= lineno_len;
        location->message = sr_strdup("Unable to fin the ':' character "
                                      "preceding the line number");
        goto fail;
    }

    /* Everything before the colon is the file name. */
    *p = '\0';
    frame->file_name = filename_lineno_in;
    filename_lineno_in = NULL;

    if(!sr_skip_char(&local_input, '`'))
    {
        location->message = sr_strdup("Unable to find the '`' character "
                                      "identifying the beginning of function name.");
        goto fail;
    }

    location->column++;

    /* The part in quotes can look like:
     * `rescue in rescue in block (3 levels) in func'
     * parse the number of rescues and blocks
     */
    while (sr_skip_string(&local_input, "rescue in "))
    {
        frame->rescue_level++;
        location->column += strlen("rescue in ");
    }

    if (sr_skip_string(&local_input, "block in "))
    {
        frame->block_level = 1;
        location->column += strlen("block in");
    }
    else if(sr_skip_string(&local_input, "block ("))
    {
        location->column += strlen("block (");

        int len = sr_parse_uint32(&local_input, &frame->block_level);
        if (len == 0 || !sr_skip_string(&local_input, " levels) in "))
        {
            location->message = sr_strdup("Unable to parse block depth.");
            goto fail;
        }
        location->column += len + strlen(" levels) in ");
    }

    if (sr_skip_char(&local_input, '<'))
    {
        location->column++;
        frame->special_function = true;
    }

    if (!sr_parse_char_cspan(&local_input, "'>", &frame->function_name))
    {
        location->message = sr_strdup("Unable to find the \"'\" character "
                                      "delimiting the function name.");
        goto fail;
    }
    location->column += strlen(frame->function_name);

    if (frame->special_function)
    {
        if (!sr_skip_char(&local_input, '>'))
        {
            location->message = sr_strdup("Unable to find the \">\" character "
                                          "delimiting the function name.");
            goto fail;
        }
        location->column++;
    }

    if (!sr_skip_char(&local_input, '\''))
    {
        location->message = sr_strdup("Unable to find the \"'\" character "
                                      "delimiting the function name.");
        goto fail;
    }
    location->column++;

    *input = local_input;
    return frame;

fail:
    sr_ruby_frame_free(frame);
    free(filename_lineno_in);
    return NULL;
}
Example #4
0
struct sr_python_stacktrace *
sr_python_stacktrace_parse(const char **input,
                           struct sr_location *location)
{
    const char *local_input = *input;

    /* Parse the header. */
    if (sr_skip_char(&local_input, '\n'))
        location->column += 1;

    const char *HEADER = "Traceback (most recent call last):\n";
    local_input = sr_strstr_location(local_input,
                                     HEADER,
                                     &location->line,
                                     &location->column);

    if (!local_input)
    {
        /* SyntaxError stack trace of an exception thrown in the executed file
         * conforms to the following template:
         * invalid syntax ($file, line $number)
         *
         *    File "$file", line $number
         *       $code
         *         ^
         * SyntaxError: invalid syntax
         *
         * for exceptions thrown from imported files, the stack trace has the
         * regular form, except the last frame has no function name and is
         * followed by the pointer line (^).
         */
        HEADER = "invalid syntax (",
        local_input = sr_strstr_location(*input,
                                     HEADER,
                                     &location->line,
                                     &location->column);

        if (!local_input)
        {
            location->message = "Traceback header not found.";
            return NULL;
        }

        local_input = sr_strstr_location(local_input,
                           "  File \"",
                           &location->line,
                           &location->column);

        if (!local_input)
        {
            location->message = "Frame with invalid line not found.";
            return NULL;
        }
    }
    else
    {
        local_input += strlen(HEADER);
        location->line += 2;
        location->column = 0;
    }

    struct sr_python_stacktrace *stacktrace = sr_python_stacktrace_new();

    /* Read the frames. */
    struct sr_python_frame *frame;
    struct sr_location frame_location;
    sr_location_init(&frame_location);
    while ((frame = sr_python_frame_parse(&local_input, &frame_location)))
    {
        /*
         * Python stacktraces are in reverse order than other types - we
         * reverse it here by prepending each frame to the list instead of
         * appending it.
         */
        frame->next = stacktrace->frames;
        stacktrace->frames = frame;

        sr_location_add(location,
                        frame_location.line,
                        frame_location.column);
    }

    if (!stacktrace->frames)
    {
        location->message = frame_location.message;
        sr_python_stacktrace_free(stacktrace);
        return NULL;
    }

    bool invalid_syntax_pointer = true;
    const char *tmp_input = local_input;
    while (*tmp_input != '\n' && *tmp_input != '\0')
    {
        if (*tmp_input != ' ' && *tmp_input != '^')
        {
            invalid_syntax_pointer = false;
            break;
        }
        ++tmp_input;
    }

    if (invalid_syntax_pointer)
    {
        /* Skip line "   ^" pointing to the invalid code */
        sr_skip_char_cspan(&local_input, "\n");
        ++local_input;
        ++location->line;
        location->column = 1;
    }

    /* Parse exception name. */
    if (!sr_parse_char_cspan(&local_input, ":\n", &stacktrace->exception_name))
    {

        location->message = "Unable to find the ':\\n' characters "
                            "identifying the end of exception name.";
        sr_python_stacktrace_free(stacktrace);
        return NULL;

    }

    *input = local_input;
    return stacktrace;
}
Example #5
0
struct sr_koops_stacktrace *
sr_koops_stacktrace_parse(const char **input,
                          struct sr_location *location)
{
    const char *local_input = *input;

    struct sr_koops_stacktrace *stacktrace = sr_koops_stacktrace_new();
    struct sr_koops_frame *frame;
    bool parsed_ip = false;
    char *alt_stack = NULL;

    /* Include the raw kerneloops text */
    stacktrace->raw_oops = sr_strdup(*input);

    /* Looks for the "Tainted: " line in the whole input */
    parse_taint_flags(local_input, stacktrace);

    while (*local_input)
    {
        sr_skip_char_span(&local_input, " \t");

        /* Skip timestamp if it's present. */
        sr_koops_skip_timestamp(&local_input);
        sr_skip_char_span(&local_input, " \t");

        /* Not sure what it means on s390x but i think it's at the end of the
         * stack
         */
        if (sr_skip_string(&local_input, "Last Breaking-Event-Address:\n"))
        {
            while (*local_input)
                local_input++;
            break;
        }

        if (!stacktrace->modules &&
            (stacktrace->modules = sr_koops_stacktrace_parse_modules(&local_input)))
            goto next_line;

        if (!parsed_ip &&
            (frame = parse_IP(&local_input)))
        {
            /* this is the very first frame (even though for i386 it's at the
             * end), we need to prepend it */
            stacktrace->frames = sr_koops_frame_prepend(stacktrace->frames, frame);
            parsed_ip = true;
            goto next_line;
        }

        /* <IRQ>, <NMI>, ... */
        if (parse_alt_stack_end(&local_input))
        {
            free(alt_stack);
            alt_stack = NULL;
        }

        /* <EOI>, <<EOE>> */
        char *new_alt_stack = parse_alt_stack_start(&local_input);
        if (new_alt_stack)
        {
            alt_stack = new_alt_stack;
        }

        if((frame = sr_koops_frame_parse(&local_input)))
        {
            if (alt_stack)
                frame->special_stack = sr_strdup(alt_stack);

            stacktrace->frames = sr_koops_frame_append(stacktrace->frames, frame);
            goto next_line;
        }

        sr_skip_char_cspan(&local_input, "\n");

next_line:
        sr_skip_char(&local_input, '\n');
    }

    *input = local_input;
    return stacktrace;
}
Example #6
0
struct sr_python_frame *
sr_python_frame_parse(const char **input,
                      struct sr_location *location)
{
    const char *local_input = *input;

    if (0 == sr_skip_string(&local_input, "  File \""))
    {
        location->message = sr_asprintf("Frame header not found.");
        return NULL;
    }

    location->column += strlen("  File \"");
    struct sr_python_frame *frame = sr_python_frame_new();

    /* Parse file name */
    if (!sr_parse_char_cspan(&local_input, "\"", &frame->file_name))
    {
        location->message = sr_asprintf("Unable to find the '\"' character "
                "identifying the beginning of file name.");

        goto fail;
    }

    if (strlen(frame->file_name) > 0 &&
        frame->file_name[0] == '<' &&
        frame->file_name[strlen(frame->file_name)-1] == '>')
    {
        frame->special_file = true;
        frame->file_name[strlen(frame->file_name)-1] = '\0';
        char *inside = sr_strdup(frame->file_name + 1);
        free(frame->file_name);
        frame->file_name = inside;
    }

    frame->file_name = anonymize_path(frame->file_name);

    location->column += strlen(frame->file_name);

    if (0 == sr_skip_string(&local_input, "\", line "))
    {
        location->message = sr_asprintf("Line separator not found.");
        goto fail;
    }

    location->column += strlen("\", line ");

    /* Parse line number */
    int length = sr_parse_uint32(&local_input, &frame->file_line);
    if (0 == length)
    {
        location->message = sr_asprintf("Line number not found.");
        goto fail;
    }

    location->column += length;

    if (0 == sr_skip_string(&local_input, ", in "))
    {
        if (local_input[0] != '\n')
        {
            location->message = sr_asprintf("Function name separator not found.");
            goto fail;
        }

        /* The last frame of SyntaxError stack trace does not have
         * function name on its line. For the sake of simplicity, we will
         * believe that we are dealing with such a frame now.
         */
        frame->function_name = sr_strdup("syntax");
        frame->special_function = true;
    }
    else
    {
        location->column += strlen(", in ");

        /* Parse function name */
        if (!sr_parse_char_cspan(&local_input, "\n", &frame->function_name))
        {
            location->message = sr_asprintf("Unable to find the newline character "
                    "identifying the end of function name.");

            goto fail;
        }

        location->column += strlen(frame->function_name);

        if (strlen(frame->function_name) > 0 &&
            frame->function_name[0] == '<' &&
            frame->function_name[strlen(frame->function_name)-1] == '>')
        {
            frame->special_function = true;
            frame->function_name[strlen(frame->function_name)-1] = '\0';
            char *inside = sr_strdup(frame->function_name + 1);
            free(frame->function_name);
            frame->function_name = inside;
        }
    }

    if (sr_skip_char(&local_input, '\n'))
        sr_location_add(location, 1, 0);

    /* Parse source code line (optional). */
    if (4 == sr_skip_string(&local_input, "    "))
    {
        if (sr_parse_char_cspan(&local_input, "\n", &frame->line_contents)
                && sr_skip_char(&local_input, '\n'))
            sr_location_add(location, 1, 0);
    }

    *input = local_input;
    return frame;

fail:
    sr_python_frame_free(frame);
    return NULL;
}