Project

General

Profile

[logo] 
 
Home
News
Activity
About/Contact
Major Tools
  Dinotrace
  Verilator
  Verilog-mode
  Verilog-Perl
Other Tools
  IPC::Locker
  Parallel::Forker
  Voneline
General Info
  Papers

0001-Refactor-VL_WRITEMEM_N-address-range-checking.patch

Sergey Kvachonok, 05/14/2019 07:10 AM

Download (3.16 KB)

View differences:

include/verilated.cpp
1303 1303
    const std::string& filename,  // Output file name
1304 1304
    const void* memp,  // Array state
1305 1305
    IData start,  // First array row address to write
1306
    IData end  // Last address to write
1306
    IData end  // Last address to write, or ~0 when not specified
1307 1307
    ) VL_MT_SAFE {
1308 1308
    if (VL_UNLIKELY(!hex)) {
1309 1309
        VL_FATAL_MT(filename.c_str(), 0, "",
1310 1310
                    "VL_WRITEMEM_N only supports hex format for now, sorry!");
1311 1311
        return;
1312 1312
    }
1313

  
1314
    // Calculate row address limits
1315
    size_t row_min = array_lsb;
1316
    size_t row_max = row_min + depth - 1;
1317

  
1318
    // Normalize the last address argument: ~0 => row_max
1319
    size_t nend = (end == ~0u) ? row_max : end;
1320

  
1321
    // Bounds check the write address range
1322
    if (VL_UNLIKELY((start < row_min) || (start > row_max)
1323
                  || (nend < row_min) ||  (nend > row_max))) {
1324
        VL_FATAL_MT(filename.c_str(), 0, "",
1325
                    "$writemem specified address out-of-bounds");
1326
        return;
1327
    }
1328

  
1329
    if (VL_UNLIKELY(start > nend)) {
1330
        VL_FATAL_MT(filename.c_str(), 0, "",
1331
                    "$writemem invalid address range");
1332
        return;
1333
    }
1334

  
1335
    // Calculate row offset range
1336
    size_t row_start = start - row_min;
1337
    size_t row_end   = nend  - row_min;
1338

  
1339
    // Bail out on possible 32-bit size_t overflow
1340
    if (VL_UNLIKELY(row_end + 1 == 0)) {
1341
        VL_FATAL_MT(filename.c_str(), 0, "",
1342
                    "$writemem address is too large");
1343
        return;
1344
    }
1345

  
1313 1346
    FILE* fp = fopen(filename.c_str(), "w");
1314 1347
    if (VL_UNLIKELY(!fp)) {
1315 1348
        VL_FATAL_MT(filename.c_str(), 0, "", "$writemem file not found");
1316 1349
        return;
1317 1350
    }
1318 1351

  
1319
    for (int row_addr = start; row_addr <= end; ++row_addr) {
1320
        if ((row_addr < array_lsb)
1321
            || (row_addr > array_lsb + depth - 1)) {
1322
            vluint32_t endmax = ~0;
1323
            if (end != endmax) {
1324
                VL_FATAL_MT(filename.c_str(), 0, "",
1325
                            "$writemem specified address out-of-bounds");
1326
            }
1327
            // else, it's not an error to overflow due to end == endmax,
1328
            // just return cleanly.
1329
            goto cleanup;
1330
        }
1331

  
1332
        // Compute the offset into the memp array.
1333
        int row_offset = row_addr - array_lsb;
1334

  
1352
    for (size_t row_offset = row_start; row_offset <= row_end; ++row_offset) {
1335 1353
        if (width <= 8) {
1336 1354
            const CData* datap
1337 1355
                = &(reinterpret_cast<const CData*>(memp))[row_offset];
......
1380 1398
        }
1381 1399
    }
1382 1400

  
1383
  cleanup:
1384 1401
    fclose(fp);
1385 1402
}
1386 1403

  
1387
-