Skip to content

Stop reading values once the declared count is reached - #473

Open
arpitjain099 wants to merge 3 commits into
ORNL:developfrom
arpitjain099:fix/bound-matrix-market-readers
Open

arpitjain099 wants to merge 3 commits into
ORNL:developfrom
arpitjain099:fix/bound-matrix-market-readers

Conversation

@arpitjain099

Copy link
Copy Markdown

The Matrix Market readers in resolve/matrix/io.cpp take the length from the header, allocate that much, and then read until end of file:

real_type* vec = new real_type[n];
real_type  a;
while (file >> a)
{
  vec[i] = a;
  i++;
}

A file whose header says 4 and whose body carries 12 values therefore writes past the end. Built with -fsanitize=address:

ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 8
    ReSolve::io::createArrayFromFile(...) io.cpp:272

createVectorFromFile is the same shape. updateVectorFromFile is the interesting one: it does check n != vec_rhs->getSize(), but that compares the declared length, so a header that matches exactly followed by 300 extra values passes the check and then overflows anyway.

Each loop now stops at the declared count. Afterwards a well-formed file reads identically, the over-long one keeps the first four values, and the update case leaves the vector at its size with nothing reported by the sanitizer. updateArrayFromFile has the same shape and carries a @todo from you saying the risk of writing past the end is high; it is bounded here too.

createArrayFromFile and createVectorFromFile size the allocation from the
Matrix Market header and then read to end of file, so a body longer than the
header declares is written past the end. updateVectorFromFile compares the
declared length against the vector size and then does the same, so a header
that matches exactly plus extra values passes the check and still overflows.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
The fourth reader in this file has the same unbounded loop and carries a todo
from the maintainers saying the risk of writing past the end is high.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@arpitjain099

Copy link
Copy Markdown
Author

Correction to my own description: when I opened this, updateArrayFromFile was still unbounded, so the last sentence was wrong at the time I wrote it. I have pushed a second commit that bounds it the same way, and all four loops in the file now stop at the declared count.

@pelesh

pelesh commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

@arpitjain099, thanks for your contribution. My suggestion would be:

  • If the declared number of entries (NNZ) does not agree with the number of entries read, the reader should exit with an error. The file is malformed and should not be used.
  • Optionally, we could ignore empty lines at the end of the file.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@arpitjain099

Copy link
Copy Markdown
Author

Done, pushed as a third commit.

All four readers now compare the number of entries read against the header and return without touching the caller's data when they disagree. Too few entries and too many are both rejected; the body goes into a temporary first, so a malformed file leaves the target vector alone rather than half written. Trailing blank lines come for free, since operator>> skips whitespace, so the check for an extra entry does not see them.

New test rhsVectorLengthMismatch covers a short body, a long body and a file with trailing blank lines, for createArrayFromFile, createVectorFromFile and updateVectorFromFile. It fails on the previous commit and passes now. Full unit suite is 50/50 on a CPU-only build.

One thing I noticed but left alone: updateArrayFromFile never assigns back to *p_rhs, so when it allocates the array the caller never sees it and it leaks. Happy to fix that here or in a separate PR, whichever you prefer.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants