Repository navigation
stream buffer after free
Alexander Liberov edited this page Nov 5, 2026
·
1 revision
A pointer into a memory stream's buffer is used after the stream was freed. The memory went with the stream, so the pointer dangles. OFF by default.
S := TMemoryStream.Create;
try
P := S.Memory;
finally
S.Free;
end;
Consume(P); // findingdrag-lint lint <file> --rule stream-buffer-after-free
drag-lint lint-all --db <project.sqlite> --rule stream-buffer-after-free
To keep it on, add it to "enabled" in drag-lint-lint.json.
- The stream: a local typed
TMemoryStream,TBytesStream,TStringStream,TCustomMemoryStreamorTResourceStream, or a class the index knows descends fromTCustomMemoryStream. - The pointer: a local typed
PointerorP<Name>, or an inlinevar, assignedS.Memory,@S.Bytes[n]orPointer(S.Bytes), through casts and pointer arithmetic. - The free:
S.Free,S.DestroyorFreeAndNil(S), in the routine's main line or afinally.
- A
TBytescopy ofS.Bytes. A dynamic array is reference-counted, so it outlives the stream. This is why the old "dangling TBytes" candidate became a rule about pointers. - A free inside
if,case, a loop,withorexcept: it may not have run when the use is reached. - A pointer assigned again between the free and the use.
- A field or a parameter: the rule follows locals only.