Skip to content

GH-45497: [C++][CSV] Avoid buffer overflow when a line has too many columns - #45498

Merged
pitrou merged 3 commits into
apache:mainfrom
pitrou:csv-vuln
Feb 12, 2025
Merged

pitrou merged 3 commits into
apache:mainfrom
pitrou:csv-vuln

Conversation

@pitrou

@pitrou pitrou commented Feb 11, 2025 •

Copy link
Copy Markdown
Member

What changes are included in this PR?

  1. Add guard against going past the buffer's end, while minimizing the performance overhead of the runtime check.
  2. Add error propagation for buffer (re)allocation, instead of aborting. This is unrelated to the reported issue, but is desirable nevertheless.

With these changes, a CSV line with an unexpectedly large number of columns will raise an error such as "CSV parse error: Expected 13 columns, got ...".

Are these changes tested?

Yes, by additional unit tests.

Are there any user-facing changes?

No.

@pitrou pitrou changed the title GH-45497: [C++][CSV] Avoid buffer overflow when a line has too many c… GH-45497: [C++][CSV] Avoid buffer overflow when a line has too many columns Feb 11, 2025
@github-actions github-actions Bot added the awaiting review Awaiting review label Feb 11, 2025
@pitrou pitrou added the Critical Fix Bugfixes for security vulnerabilities, crashes, or invalid data. label Feb 11, 2025
@pitrou
pitrou marked this pull request as ready for review February 11, 2025 15:12
@pitrou

pitrou commented Feb 11, 2025

Copy link
Copy Markdown
Member Author

@github-actions crossbow submit -g cpp

@pitrou

pitrou commented Feb 11, 2025

Copy link
Copy Markdown
Member Author

@ursabot please benchmark

@ursabot

ursabot commented Feb 11, 2025

Copy link
Copy Markdown

Benchmark runs are scheduled for commit 463fe8c23da28dcea4c7fae2d712cc661295a844. Watch https://buildkite.com/apache-arrow and https://conbench.ursa.dev for updates. A comment will be posted here when the runs are complete.

@github-actions

This comment was marked as outdated.

@pitrou

pitrou commented Feb 11, 2025 •

Copy link
Copy Markdown
Member Author

@zanmato1984 Sorry for pinging you once again! I'm looking for reviewers on this PR :)

@conbench-apache-arrow

Copy link
Copy Markdown

Thanks for your patience. Conbench analyzed the 4 benchmarking runs that have been run so far on PR commit 463fe8c23da28dcea4c7fae2d712cc661295a844.

There were 14 benchmark results indicating a performance regression:

The full Conbench report has more details.

Comment thread cpp/src/arrow/csv/parser.cc Outdated
Comment on lines 176 to 179

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the Resize() failed, is values_[values_size_++] = v safe?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that's a good point. We might adopt the same kind of approach as in the presized writer below.

Comment thread cpp/src/arrow/csv/parser_test.cc Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need 2, 5, 10 here? 1, 100 aren't enough?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditions for triggering the issue are bit mysterious, so I thought it would be safer to ensure non-regression with a larger set of parameters. I can trim it down a bit of course.

Comment thread cpp/src/arrow/csv/parser_test.cc Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need all these cases?
It seems that -1, 1, 32767 are enough.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same answer as above :)

@github-actions github-actions Bot added awaiting changes Awaiting changes and removed awaiting review Awaiting review labels Feb 12, 2025
Comment thread cpp/src/arrow/csv/parser.cc Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when !status_.ok(), the values_buffer_ isn't gurantee to exist?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will probably exist, but it might not be large enough.

Comment thread cpp/src/arrow/csv/parser.cc Outdated
Comment thread cpp/src/arrow/csv/parser.cc Outdated
Comment thread cpp/src/arrow/csv/parser_test.cc Outdated

@zanmato1984 zanmato1984 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than kou's comment about the writing in ResizableValueDescWriter when Resize failed, this LGTM.

…many columns

* Add guard against going past the buffer's end, while minimizing the performance overhead of the runtime check

* Add error propagation for buffer (re)allocation, instead of aborting
@pitrou

pitrou commented Feb 12, 2025

Copy link
Copy Markdown
Member Author

@github-actions crossbow submit -g cpp

@pitrou

pitrou commented Feb 12, 2025

Copy link
Copy Markdown
Member Author

@ursabot please benchmark

@ursabot

ursabot commented Feb 12, 2025

Copy link
Copy Markdown

Benchmark runs are scheduled for commit 2d1965f. Watch https://buildkite.com/apache-arrow and https://conbench.ursa.dev for updates. A comment will be posted here when the runs are complete.

@github-actions github-actions Bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Feb 12, 2025
@github-actions

Copy link
Copy Markdown

Revision: 2d1965f

Submitted crossbow builds: ursacomputing/crossbow @ actions-4b9f129152

Task Status
example-cpp-minimal-build-static GitHub Actions
example-cpp-minimal-build-static-system-dependency GitHub Actions
example-cpp-tutorial GitHub Actions
test-alpine-linux-cpp GitHub Actions
test-build-cpp-fuzz GitHub Actions
test-conda-cpp GitHub Actions
test-conda-cpp-valgrind GitHub Actions
test-cuda-cpp-ubuntu-20.04-cuda-11.2.2 GitHub Actions
test-cuda-cpp-ubuntu-22.04-cuda-11.7.1 GitHub Actions
test-debian-12-cpp-amd64 GitHub Actions
test-debian-12-cpp-i386 GitHub Actions
test-fedora-39-cpp GitHub Actions
test-ubuntu-20.04-cpp GitHub Actions
test-ubuntu-20.04-cpp-bundled GitHub Actions
test-ubuntu-22.04-cpp GitHub Actions
test-ubuntu-22.04-cpp-20 GitHub Actions
test-ubuntu-22.04-cpp-emscripten GitHub Actions
test-ubuntu-22.04-cpp-no-threading GitHub Actions
test-ubuntu-24.04-cpp GitHub Actions
test-ubuntu-24.04-cpp-bundled-offline GitHub Actions
test-ubuntu-24.04-cpp-gcc-13-bundled GitHub Actions
test-ubuntu-24.04-cpp-gcc-14 GitHub Actions
test-ubuntu-24.04-cpp-minimal-with-formats GitHub Actions
test-ubuntu-24.04-cpp-thread-sanitizer GitHub Actions

@pitrou

pitrou commented Feb 12, 2025 •

Copy link
Copy Markdown
Member Author

(by the way, do we have an open issue for the failing Debian builds? @kou)

@kou

kou commented Feb 12, 2025

Copy link
Copy Markdown
Member

GH-45510

@pitrou

pitrou commented Feb 12, 2025

Copy link
Copy Markdown
Member Author

I think I've addressed all review comments. Does someone want to take a quick look or should I merge?

@zanmato1984 zanmato1984 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one question.

}
status_ &= std::move(resize_status);
}
if (ARROW_PREDICT_TRUE(status_.ok())) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not the same approach as PresizedValueDescWriter as you mentioned before? Less perf hurting?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned by @mapleFU above, the pointer might not be valid anymore if the resize failed.

Also, this is less performance-critical as this is normally run only on the first line of data.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could add comments to explain this if that's useful.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned by @mapleFU above, the pointer might not be valid anymore if the resize failed.

Ah, good point.

Also, this is less performance-critical as this is normally run only on the first line of data.

I don't think that's necessary. Do it as you wish.

@pitrou
pitrou merged commit 25d8bed into apache:main Feb 12, 2025
@pitrou pitrou removed the awaiting change review Awaiting change review label Feb 12, 2025
@pitrou
pitrou deleted the csv-vuln branch February 12, 2025 12:54
@conbench-apache-arrow

Copy link
Copy Markdown

Thanks for your patience. Conbench analyzed the 4 benchmarking runs that have been run so far on PR commit 2d1965f.

There were 9 benchmark results indicating a performance regression:

The full Conbench report has more details.

@conbench-apache-arrow

Copy link
Copy Markdown

After merging your PR, Conbench analyzed the 4 benchmarking runs that have been run so far on merge-commit 25d8bed.

There were no benchmark performance regressions. 🎉

The full Conbench report has more details. It also includes information about 15 possible false positives for unstable benchmarks that are known to sometimes produce them.

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

Labels

Component: C++ Critical Fix Bugfixes for security vulnerabilities, crashes, or invalid data.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants