SQLite Forum

DATA RACE 2: Found in sqlite3.c
Login

DATA RACE 2: Found in sqlite3.c

(1) By Zu-Ming Jiang (jiang446079653) on 2020-04-29 03:32:30 [source]

Dear SQLite developers:

I used my fuzz-testing tool, connzer, to detect data race in SQLite. Here is a data race found by connzer. I wish you can help me check whether it is a real race, thanks!!

The following is the race report.

Race report

Version: 3.30.1

Race object: pShmNode->pShmMutex

Thread 1:

Access: pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);

Line number: sqlite3.c, 37258

Call stack:

  1. unixOpenSharedMemory()
  2. unixShmMap()
  3. sqlite3OsShmMap()
  4. walIndexPageRealloc()
  5. walIndexPage()
  6. walIndexReadHdr()
  7. walTryBeginRead()
  8. sqlite3WalBeginReadTransaction()
  9. pagerBeginReadTransaction()
  10. sqlite3PagerSharedLock()
  11. lockBtree()
  12. sqlite3BtreeBeginTrans()
  13. sqlite3VdbeExec()
  14. sqlite3Step()
  15. sqlite3_step()
  16. sqlite3_exec()
  17. sql_script_x()
  18. walthread2_thread()
  19. launch_thread_main()

Lock: unixEnterMutex()

Thread 2:

Access: sqlite3_mutex_enter(pShmNode->pShmMutex);

Line number: sqlite3.c; 37305

Call stack:

  1. unixOpenSharedMemory()
  2. unixShmMap()
  3. sqlite3OsShmMap()
  4. walIndexPageRealloc()
  5. walIndexPage()
  6. walIndexReadHdr()
  7. walTryBeginRead()
  8. sqlite3WalBeginReadTransaction()
  9. pagerBeginReadTransaction()
  10. sqlite3PagerSharedLock()
  11. lockBtree()
  12. sqlite3BtreeBeginTrans()
  13. sqlite3BtreeSetVersion()
  14. sqlite3VdbeExec()
  15. sqlite3Step()
  16. sqlite3_step()
  17. sqlite3_exec()
  18. sql_script_x()
  19. walthread2_thread()
  20. launch_thread_main()

Lock: sqlite3_mutex_enter(pShmNode->pShmMutex)

Impact: This race may cause serious consequence: if the race access in thread 2 is executed before the race access in thread 1, pShmNode->pShmMutex in unixOpenSharedMemory() in thread 2 will be uninitialized, and sqlite3_mutex_enter(pShmNode->pShmMutex) will cause crash.

My fuzzer finds that these 2 accesses can be executed concurrently, and they are protected by different locks, so my fuzzer report this race.

(2) By Zu-Ming Jiang (jiang446079653) on 2020-05-02 07:29:53 in reply to 1 [link] [source]

What do you think about this data race?

(3) By Richard Hipp (drh) on 2020-05-02 11:24:17 in reply to 2 [link] [source]

Your analysis is incorrect.

This is no code path that reaches line sqlite3.c:37305 with pShmNode->pShmMutex uninitialized in a thread-safe build. Every path to sqlite3.c:37305 must traverse this code:

  unixEnterMutex();
  pInode = pDbFd->pInode;
  pShmNode = pInode->pShmNode;
  if( pShmNode==0 ){
    /*...*/
    if( sqlite3GlobalConfig.bCoreMutex ){
      pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    }
    /*...*/
  }
  unixLeaveMutex();

Assuming the sqlite3GlobalConfig.bCoreMutex global variable is true, that means that pShmNode->pShmMutex must be initialized prior to use.

Your tool is perhaps confused because it assumes that sqlite3GlobalConfig.bCoreMutex might be false. But that is only true if SQLite is running in "single-threaded mode".

I suppose your tool is technically correct - there is a data race if you have configured SQLite for single-threaded mode. But that does not really count, since the documentation clearly states that in single-threaded mode, SQLite is not threadsafe.

(4) By Zu-Ming Jiang (jiang446079653) on 2020-05-03 02:00:03 in reply to 3 [link] [source]

Yes, you are right.

Thanks for your response!!