Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault in multi-threaded environment in jq 1.6 #2545

Closed
thalman opened this issue Mar 1, 2023 · 1 comment
Closed

Segfault in multi-threaded environment in jq 1.6 #2545

thalman opened this issue Mar 1, 2023 · 1 comment
Labels

Comments

@thalman
Copy link
Contributor

thalman commented Mar 1, 2023

Describe the bug
When jq library is used in multiple threads it fails with coredump

To Reproduce
following code reproduces the issue. It is based on what mod_auth_openidc does

#include <stdlib.h>
#include <jq.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

int my_jq_parse(jq_state *jq, struct jv_parser *parser)
{
    int rv = 0;
    jv value;

    value = jv_parser_next(parser);
    while (jv_is_valid(value)) {
        jq_start(jq, value, 0);
        jv result;

        while (jv_is_valid(result = jq_next(jq))) {
            jv dumped = jv_dump_string(result, 0);
            const char *str = jv_string_value(dumped);
            printf("dumped: %s\n", str);
        }

        jv_free(result);
        value = jv_parser_next(parser);
    }

    if (jv_invalid_has_msg(jv_copy(value))) {
        jv msg = jv_invalid_get_msg(value);
        printf("invalid: %s\n", jv_string_value(msg));
        jv_free(msg);
        rv = 1;
    } else {
        jv_free(value);
    }

    return rv;
}

void *run(void *not_used) {
    int rv;
    jq_state *jq;
    const char *prg = ".data";

    jq = jq_init();
    printf("jq_init jq: %p prg: %s\n", jq, prg);
    if (jq_compile(jq, prg) == 0) {
        jq_teardown(&jq);
        return NULL;
    }
    printf("compiled\n");

    struct jv_parser *parser = jv_parser_new(0);
    const char *buf = "{ \"data\": 1 }";
    jv_parser_set_buf(parser, buf, strlen(buf), 0);
    rv = my_jq_parse(jq, parser);
    if (rv != 0) {
        printf("my_jq_parse failed!\n");
    }

    jv_parser_free(parser);
    jq_teardown(&jq);
    return NULL;
}

#define THREADS 2
/* calling run() twice works fine */
/* calling them in threads causes core-dump */
int main (int argc, char *argv[])
{
    pthread_t threads[THREADS];
    int createerror;
    int a;

     memset(&threads, 0, sizeof(threads));
    for (a = 0; a < THREADS; ++a) {
        // sleep(1); // < if you want to run threads sequentionally 
        createerror = pthread_create(&threads[a], NULL, run, NULL);
        if (createerror) {
            printf("create thread error %d\n", a);
        }
    }
    for(a = 0; a < THREADS; ++a) {
        if (threads[a] != 0) {
            pthread_join(threads[a], NULL);
        }
    }

    return 0;
}

Expected behavior
Code should run without core dump ;-)

Environment (please complete the following information):

  • OS and Version: Fedora 37 (and others), RHEL8, RHEL9
  • jq version: 1.6

Additional context
The issue is caused by improper use of pthred_once

@itchyny
Copy link
Contributor

itchyny commented Jul 31, 2023

#2546 has been included.

@itchyny itchyny closed this as completed Jul 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants