[llvm-bugs] [Bug 42221] New: Thrown exception jumps to wrong catch, resulting in incorrectly unhandled exceptions

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Jun 10 17:01:21 PDT 2019


https://bugs.llvm.org/show_bug.cgi?id=42221

            Bug ID: 42221
           Summary: Thrown exception jumps to wrong catch, resulting in
                    incorrectly unhandled exceptions
           Product: lld
           Version: unspecified
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: normal
          Priority: P
         Component: COFF
          Assignee: unassignedbugs at nondot.org
          Reporter: akrieger at fb.com
                CC: llvm-bugs at lists.llvm.org

We've recently seen a fairly reliably reproducible error cause by what seems to
be bad exception handling codegen. Unfortunately, the code in question is part
of a large complex project and a minimal repro case was not able to be
generated.

>From observations in the VS debugger, we see the following call stack / code
structure and steps when handling exceptions. The following is my best attempt
to describe the issue.

The 'entry point' to the stack is in one translation unit:

MetadataStorage.cpp:
```
std::string MetadataStorage::getString(const std::string& key) {
  std::string sql = dbqueries::MetadataGetValue::getSql();
  auto stmt = db_->prepareRead(sql);                                         
#1
  stmt->bind(dbqueries::MetadataGetValue::PLACEHOLDER_KEY, key);

  if (!stmt->step()) {
    throw MetadataStorage::KeyNotFoundError(key);
  }

  return stmt->getText(dbqueries::MetadataGetValue::COLUMN_VALUE);
}
```

Call #1 is where the problem occurs. #1 goes to `SqliteData::prepareRead` in
the next file,
where we call `db_.prepare(sql)` (#3):

SqliteDatabase.cpp:
```
SqliteDatabase::SqliteDatabase(const std::string& filename, int flags) try
    : db_(filename, flags),
      dbFilename_(filename) {
} catch (const sqlite::SQLiteException& e) {
  throw clientdb::DatabaseException(e.what(), e.getExtendedErrorCode());     
#2
}

SqliteDatabase::SqliteDatabase(sqlite3* db) : db_(db), dbFilename_("") {}

std::unique_ptr<clientdb::ReadStatement> SqliteDatabase::prepareRead(
    const std::string& sql) {
  try { 
    return std::make_unique<SqliteReadStatement>(db_.prepare(sql));          
#3
  } catch (const sqlite::SQLiteException& e) {
    throw clientdb::DatabaseException(e.what(), e.getExtendedErrorCode());   
#4
  }
}
```

`db_.prepare(sql)` goes to a third TU:
Database.cpp:
```
Statement Database::prepare(const std::string& sql) {
  sqlite3_stmt* stmt;
  int ret = sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr);
  if (ret != SQLITE_OK) {
    std::string strerr = sqlite3_errmsg(db_);
    int errCode = sqlite3_extended_errcode(db_);
    sqlite3_finalize(stmt);
    throw SQLiteException(strerr, errCode);                                  
#5
  }
  return Statement(*this, stmt);
}
```

What we see is the call stack goes roughly like this:
#1
#3
#5

At #5, `SQLiteException` is thrown. We would expect the catch in `prepareRead`
to fire and statement #4 to execute. Instead, the VS debugger shows control
passes to #2 (an identically formed exception handler in the same TU). From
here, the exception handling logic eventually calls terminate() and thus
abort().

Repros with: lld 7.0.0, lld 8.0.0
Does not repro with: MS link.exe, lld 9.0.0 latest snapshot (see notes below),

Notes:
- The first time this bug presented, it was masked by solving an (undetected)
multiple symbols issue in unrelated TUs linked into the final binary. The
functions were defined in a header but not marked inline. link.exe correctly
warned about this. Making them be marked inline seemed to 'resolve' the
problem, but it has since returned, in exactly the same stack and behavior.
- lld 9.0.0 most recent snapshot does _not_ reproduce the issue. However, the
fix bisects to https://reviews.llvm.org/D59797, which looks completely
unrelated to exception handling. In conjunction with the previous fix about
inlining/not inlining functions, it's possible there was a symbol ordering
change which just masks the underlying issue and doesn't solve it.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190611/affed97f/attachment.html>


More information about the llvm-bugs mailing list