<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/83828>83828</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [libfuzzer] Out-of-memory limit calculations don't work well with realloc
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          mactul
      </td>
    </tr>
</table>

<pre>
    Hi, I've noticed that libfuzzer is counting the memory allocated by `realloc` incorrectly. 
For example:
```c
void* ptr = malloc(100);
ptr = realloc(ptr, 200);
```
Here, libfuzzer counts an allocation of 300 bytes (100+200) instead of just 200.

Here's the proof:
```c
#include <stdint.h>
#include <stdlib.h>

extern int LLVMFuzzerTestOneInput(const uint8_t *Data __attribute__((unused)), size_t Size __attribute__((unused)))
{
 void* ptr = NULL;
    for(int i = 10000; i < 100000; i++)
    {
 ptr = realloc(ptr, i);
    }

    free(ptr);

    return 0;
}
```
By definition, this program only consumes 99999 bytes, which is well below libfuzzer's default limit of 256MB (2048Mb).

However, if you compile the program and run it:
```sh
clang -o clang_bug clang_bug.c -fsanitize=address,fuzzer -Wall -Wextra
./clang_bug
```
You get an out-of-memory
```
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1295557038
INFO: Loaded 1 modules   (3 inline 8-bit counters): 3 [0x62836eaa9b88, 0x62836eaa9b8b), 
INFO: Loaded 1 PC tables (3 PCs): 3 [0x62836eaa9b90,0x62836eaa9bc0), 
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
==2493== ERROR: libFuzzer: out-of-memory (used: 2855Mb; limit: 2048Mb)
   To change the out-of-memory limit use -rss_limit_mb=<N>

Live Heap Allocations: 24233028 bytes in 20 chunks; quarantined: 249670930 bytes in 9176 chunks; 51767 other chunks; total chunks: 60963; showing top 95% (at most 8 unique contexts)
24121072 byte(s) (99%) in 8 allocation(s)
```

My hypothesis is that the memory calculated is in fact the sum of i from 10000 to 100000.
This makes `99999*100000/2 - 9999*10000/2` or `4949955000` bytes, so about 4.6GB, well beyond libfuzzer's default limit.

This hypothesis seems even more credible to me if you consider that this program poses no problems:
```c
#include <stdint.h>
#include <stdlib.h>

extern int LLVMFuzzerTestOneInput(const uint8_t *Data __attribute__((unused)), size_t Size __attribute__((unused)))
{
 void* ptr = NULL;
    for(int i = 10000; i < 100000; i++)
    {
 free(ptr);
        ptr = malloc(i);
    }

 free(ptr);

    return 0;
}
```

I use clang version 16.0.6 on Arch Linux.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsV0uT4jjy_zTikgEh5Af2gQMUw787oqp7oqf_O7EnQpYTrGlZYvQoivr0G5JdPKardi67tyUIQFIqX_7lLxPunDxoxCUp1qTYTHjwnbHLngsf1KQx7Xn5SRL2AJ8JWzwjaOOlwBZ8xz0o2ezD6ytakA6ECdpLfQDfIfTYG3sGrpQR3GMLzRlISS2mHVJSkFoYa1F4dZ4BoRtCV1tjAV94f1RIstWwR0o6vMWwfjayJWwFR2-BZBvoB4WsmlNKWE2y9SD3dv5mkVVHb2Mc7F7uon9YfkKLUeoaWQrLAddvwUijwewhoxSas0cHb8bXg2qQ2nnkbRT6IzgfLc5GYzc2Fi4l6miN2X8YLWGZ1EKFFoFkD863UvtZR7JfPjhWsrk9Tp_44tFqkNrD4-M_nrYprO_o_FeNn_UxeMIqYbTzEKT21c4DYasN9xx2O-69lU3wuNsRVhFWBR0ctjGB8f0ATr7izsNv8hX_Xrwe3VqMuYe_Pswv___4eHkyAAB7YwmrousyCcwppZRk67R8GJbDmrB1etfXy1c7H4JB3kJhuLO5zV3ywSK-3bjBzeXcog9WA70eXXTcY2t9hhb3UssIoWjdd9JFABws78FodYb4HEKPDur4GvAVJU-dFF0sshMqBQ0qc7pCNGGpxT0PKpZkL32EHivKp3XEJqN59dQQVt-D0JzwGYck7OFsAgjTH6XCN1Qmp7huwQYN0v8MUdcNG0JxfYCpgfRj14TD9ddMwHTveAz5FUm24W1r0cWQxuqa_s6Vgunv-OItH_TNCNteFLybyH-aAAf0sSZN8FOznw50867w5y_bryRbwbegdWSnk_QdoPbWHKWAozmhBSc6bIPCmC76st3GrAx8MrtX8htiG7_nrC6KYkGz6v780fAWW5hDb6I-FxHFqgykVlIjVNNG-oFR0LoEpxVkQIo1fSlZlZXIed1UVbR_t9OM5faBtV8fwPNGDVyUwa8PH-quKWEPtxuCvqt62vOXnUIdMaeNj4B4lm0Mfh2BN5AInKRS6fiAGi33CDISigPF7QFtbBIaclqXI5LvTKxAGHsM7icTkVY8t6mX7K2JKATsj_48Xhgfc7Yh2YbldTb8gl--ffv6LSq--BcXdwCJ6UmElK2AVUXx1Azx9AnfcKmUS3F_NyA6rg9DVdzrGiotOISpdW6Xlru-Sd48fPkLCT_KZ4RPyI-wunQRl2zmLMsoq8ZeIjUwCqIL-oeLvv0ZuOWxrY5O53W5oHVGr-L1fFHeXCjmi3IBxnexdV12vfFcXdYrKGldZvHAdeaUerY5Ql0QVsQUcQ-9cR4qCFr-GTDSkscX7y6pYfmczemCJTcIq-JJvFnXhBVDD4TqpmGOIu8W6PD5dIbufIx-O5kgkQaMm1FCcCWCSrOETIHvuRgEXOgj4ckBLKkngDdjcxgL-Huk2p7_iCVS0sSuhK3G_sG2DKZwuxe34pBibBTP67yuiyLul_RKys4Ab0zwkM_K_1snmh7Y-Wx0--_o-Y6Ik2c3oTvE3gE-o4beWARhsZVN5GUDPV7JWjvZDiXm7xvJ0TiMFRU3GoW9-9908d-dLt4fEGB8_TSo_u3M8R8bOEa-TRw1dOlntC7Or_NyRmclGA0rKzp4lDq8zCbtMmvrrOYTXM4XtC4KRhds0i33RUbzPSuLVoi2xFLkzaKmOTZtnYmG8olcMspymtF8Ps_yjM1EscC8wabNFrkQ85LkFHsu1Uyp535m7GEinQu4rLKKVRPFG1Qu_QNhTOMJ0iFhLP4hsct4Z9qEgyM5VdJ5d9XipVfpr8u12ooNfH2Hp9_oI_IutJGRFh5Oxv4YijZNBeN4OAlWLTvvj6ly2Jaw7UH6LjQzYXrCttH6-DU9WvMHCk_YNvnsCNummP4VAAD__4H885k">