OK I think I might have found the reason. After allocating memory, SQLite is ultimately calling _msize() to get the actual amount of allocated memory, but the size returned includes the guards added by the checked heap, and it's those that later get overwritten. Sorry for wasting your time.