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

bug in 500.perlbench_r(need to be reported) #3

Open
kitaharazy opened this issue Oct 16, 2022 · 3 comments
Open

bug in 500.perlbench_r(need to be reported) #3

kitaharazy opened this issue Oct 16, 2022 · 3 comments

Comments

@kitaharazy
Copy link
Collaborator

Trigger the bug

In short, in realloc, we gonna call void Free(void *ptr, void *end) in

/home/roland/github/violet/src/safe_tcmalloc/tcmalloc/span.h:165,

during the while loop, PL_tmps_stack[330]->sv_any is end-0x10,

and it will be poisioned by Free, cur->addr == &PL_tmps_stack[330]->sv_any.

After being poisioned, PL_tmps_stack[330]->sv_any will be accessed in the following codes, so there is a segfault.


In case 500, there are several global vars, such as (SV **)PL_tmps_stack , PL_tmps_ix , PL_tmps_max, these three vars are related to this bug.

About PL_tmps_stack[330], PL_tmps_stack[330]->sv_any will be poisioned during realloc PL_tmps_stack[]

the backtrace:

#0  tcmalloc::tcmalloc_internal::EscapeTable::Free (this=0x56c33f760f78, ptr=0x56c33fbb2c80, end=0x56c33fbb3900) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/span.h:188

#1  0x00007ffff74bdef9 in tcmalloc::tcmalloc_internal::(anonymous namespace)::do_free_with_size_class<false, (tcmalloc::tcmalloc_internal::Hooks)0> (size_class=0, ptr=0x56c33fbb2c80) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/span.h:428

#2  tcmalloc::tcmalloc_internal::(anonymous namespace)::do_free (ptr=0x56c33fbb2c80) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/tcmalloc.cc:1095

#3  do_realloc (new_size=<optimized out>, old_ptr=0x56c33fbb2c80) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/tcmalloc.cc:1872

#4  TCMallocInternalRealloc (old_ptr=0x56c33fbb2c80, new_size=<optimized out>) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/tcmalloc.cc:1888

#5  0x00000000004f5180 in Perl_safesysrealloc (where=0x56c33f760f78, size=<optimized out>) at util.c:278

#6  0x00000000004bc8ba in Perl_tmps_grow_p (ix=ix@entry=386) at scope.c:161

in backtrace, &PL_tmps_stack[0] = 0x56c33fbb2c80 , &PL_tmps_stack[330] = 0x56c33fbb36d0 , &PL_tmps_stack[330]->sv_any = 0x56c33eba82e8 , PL_tmps_stack[330]->sv_any = 0x56c33fbb38f0(before being poisioned)

In do_free_with_size_class<false, (tcmalloc::tcmalloc_internal::Hooks)0> (size_class=0, ptr=PL_tmps_stack)
span_->GetEscapeTable()->Free(ptr); will finally be called as:

span_->GetEscapeTable()->Free(ptr, (char*)ptr + obj_size);

Therefore, as for PL_tmps_stack[330]->sv_any = 0x56c33fbb38f0, it is in the range of (ptr , end = obj_size+ptr) , and will be poisioned in the loop at tcmalloc/span.h:165

    // ptr=0x56c33fbb2c80, end=0x56c33fbb3900 

    while (cur) {
      if (ptr <= cur->addr && cur->addr < end) {
        struct escape* e = cur;

        if (pre == nullptr) {
          head = e->next;
          cur  = e->next;
        } else {
          pre->next = e->next;
          cur = e->next;
        }

        while (e->escape_list) {
          struct escape *cur = e->escape_list;
          e->escape_list = cur->next;

          void* cur_addr = *(reinterpret_cast<void**>(cur->addr));
          if (ptr <= cur_addr && cur_addr < end) {
            *(reinterpret_cast<size_t*>(cur->addr)) |= (size_t) 0xdeadbeef00000000;
          }
          delete_escape(cur);
        }
        delete_escape(e);
      } else {
        pre = cur;
        cur = cur->next;
      }
    }

debug script

#save as a.gdb
#`source a.gdb` after run your gdb
b *(Perl_tmps_grow_p+85) if (unsigned long)$rsi >  0x1000


b *(Perl_free_tmps+46) if (*(unsigned long *)PL_tmps_stack[PL_tmps_ix+1]) > 0x66c33e9088b0 && (unsigned long)(PL_tmps_ix) == 329


run -I./lib checkspam.pl 2500 5 25 11 150 1 1 1 1 > checkspam.2500.5.25.11.150.1.1.1.1.out 2>> checkspam.2500.5.25.11.150.1.1.1.1.err

First you will stop at Renew() before realloc is called, then use watch PL_tmps_stack[330]->sv_any and continue, you will stop at delete_escape(cur); in safe_tcmalloc/tcmalloc/span.h:188

@Markakd
Copy link
Owner

Markakd commented Oct 16, 2022

I feel like this is a bug. because the memory indeed is freed by realloc.

@Markakd
Copy link
Owner

Markakd commented Oct 17, 2022

We should report this bug to the developers. This benchmark has been run by many tools, none of them found this bug.

@kitaharazy kitaharazy changed the title bug in 500.perlbench_r bug in 500.perlbench_r(need to be reported) Oct 17, 2022
@kitaharazy
Copy link
Collaborator Author

We should report this bug to the developers. This benchmark has been run by many tools, none of them found this bug.

Sure, I found the webpage: https://www.spec.org/spec/contact.html

As what they say:

Please direct general technical questions regarding SPEC benchmark products to SPEC's staff at support@spec.org. We can provide assistance only with issues directly related to running the benchmark software. Examples of support that SPEC cannot provide include: hardware installation issues; hardware problems; non-SPEC software installation issues; non-SPEC software problems; hardware or software specific tuning.

Should we directly drop a mail to support@spec.org, or we need to find the developers of SPECCPU?

@kitaharazy kitaharazy reopened this Oct 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants