goblint/analyzer

Mutex-Meet-TID less precise than Mutex-Meet

Closed this issue · 7 comments

On this program

#include<pthread.h>
#include<stdlib.h>

void i() {
  char j, k = 0;
  int* f = malloc(8);

  while (k < j)
    k++;

  int r = *f;
}

void* l(void* args) {

};


void main() {
  pthread_t t;
  pthread_create(&t, 0, l, NULL);

  while (1)
    i();
 }

We observe

  Apron Octagon(domain: Apron Octagon, privatization: PerMutexMeetPrivTID(no-clusters,join)): [|j#1527+128.>=0; -j#1527+127.>=0; -j#1527+k#1528>=0; j#1527+k#1528+128.>=0;
    k#1528>=0; -j#1527-k#1528+382.>=0; j#1527-k#1528+128.>=0; -k#1528+255.>=0;
    -j#1527+r#1531+2147483775.>=0; j#1527+r#1531+2147483776.>=0;
    -k#1528+r#1531+2147483903.>=0; k#1528+r#1531+2147483648.>=0;
    r#1531+2147483648.>=0; -j#1527-r#1531+2147483774.>=0;
    j#1527-r#1531+2147483775.>=0; -k#1528-r#1531+2147483902.>=0;
    k#1528-r#1531+2147483647.>=0; -r#1531+2147483647.>=0|] (env: [|0> j#1527:int;
                                                                   1> k#1528:int;
                                                                   2> r#1531:int|])
  less precise than
  Apron Octagon(domain: Apron Octagon, privatization: PerMutexMeetPriv): [|j#1527+128.>=0; -j#1527+127.>=0; -j#1527+k#1528>=0; j#1527+k#1528+128.>=0;
    k#1528>=0; -j#1527-k#1528+254.>=0; j#1527-k#1528+128.>=0; -k#1528+127.>=0;
    -j#1527+r#1531+2147483775.>=0; j#1527+r#1531+2147483776.>=0;
    -k#1528+r#1531+2147483775.>=0; k#1528+r#1531+2147483648.>=0;
    r#1531+2147483648.>=0; -j#1527-r#1531+2147483774.>=0;
    j#1527-r#1531+2147483775.>=0; -k#1528-r#1531+2147483774.>=0;
    k#1528-r#1531+2147483647.>=0; -r#1531+2147483647.>=0|] (env: [|0> j#1527:int;
                                                                   1> k#1528:int;
                                                                   2> r#1531:int|])
  diff: -j#1527-k#1528+254.>=0, -k#1528+127.>=0, -k#1528+r#1531+2147483775.>=0, -k#1528-r#1531+2147483774.>=0

Mutex-Meet-TID: -k#1528+255.>=0;
Mutex-Meet: -k#1528+127.>=0;

This could be related to widening / narrowing but that seems unlikely at first glance.

The culprit seems to be enabling mutex-meet-tid from base for the TID configuration vs sticking with mutex-meet from base where TIDs are not enabled.

#include<pthread.h>
#include<stdlib.h>
struct a {
  int (*b)();
} r;

struct a* t;
int m() {}

void* j(void* arg) {};

void main() {
    pthread_t tid;
    pthread_create(&tid, 0, j, NULL);
    t = calloc(1, sizeof(struct a));
    t->b = &m;
    r = *t;
    invalidate(&t);
}

This is an example extracted from another program. Here, the difference is:

[Debug] node 9 "return (0);": Apron Octagon(domain: Apron Octagon, privatization: PerMutexMeetPrivTID(no-clusters,join)) less precise than Apron Octagon(domain: Apron Octagon, privatization: PerMutexMeetPriv)
  Apron Octagon(domain: Apron Octagon, privatization: PerMutexMeetPrivTID(no-clusters,join)): top (env: [||])
  less precise than
  Apron Octagon(domain: Apron Octagon, privatization: PerMutexMeetPriv): bottom (env: [||])
  diff: -1.>=0

The difference is there even when the relational domain is disabled completely.

It seems mutex-meet-tid considers m reachable from invalidate, whereas mutex-meet does not...

For the other program the issue is addressed by #1558.

For the original program, one can get rid of the infinite loop and ends up with:

#include<pthread.h>
#include<stdlib.h>

void i() {
    signed char j, k = 0;
    int* f = malloc(8);

    while (k < j)
      k++;

    int r = *f;
  }


void* l(void* args) {

};


void main() {
  pthread_t t;
  pthread_create(&t, 0, l, NULL);

  i();
  i();
 }

After the fixes in #1558, setting widen=join for Apron removes the precision differences. Other such effects are likely due to widening and narrowing as well.