[llvm] [SamplePGO] Handle "sequence too long" errors more gracefully (PR #114982)

Krzysztof Pszeniczny via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 5 05:08:35 PST 2024


https://github.com/amharc created https://github.com/llvm/llvm-project/pull/114982

Currently the `SampleProfileReader` calls `std::vector::reserve` directly with the `size_t` it reads from the binary format. `std::vector::reserve` will throw `std::length_error` if the value is larger than `max_size()` (which results in an `abort()` in the `-fno-exceptions` mode). Having a function return `std::error_code` in some cases of malformed inputs, but throw an exception in others is confusing. Let's return `sampleprof_error::too_large` instead.

>From f68510d23db377d99ca5b02db137de71de70da67 Mon Sep 17 00:00:00 2001
From: Krzysztof Pszeniczny <kpszeniczny at google.com>
Date: Tue, 5 Nov 2024 13:59:32 +0100
Subject: [PATCH] [SamplePGO] Handle "sequence too long" errors more gracefully

Currently the `SampleProfileReader` calls `std::vector::reserve` directly with the `size_t` it reads from the binary format. `std::vector::reserve` will throw `std::length_error` if the value is larger than `max_size()` (which results in an `abort()` in `-fno-exceptions` mode). Having a function return `std::error_code` in some cases of malformed inputs, but throw an exception in others is confusing. Let's return `sampleprof_error::too_large` instead.
---
 llvm/lib/ProfileData/SampleProfReader.cpp | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index 98c78443785275..70ae87dd22cd9a 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -857,9 +857,11 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() {
     return EC;
 
   bool UseFuncOffsetList = useFuncOffsetList();
-  if (UseFuncOffsetList)
+  if (UseFuncOffsetList) {
+    if (*Size > FuncOffsetList.max_size())
+      return sampleprof_error::too_large;
     FuncOffsetList.reserve(*Size);
-  else
+  } else
     FuncOffsetTable.reserve(*Size);
 
   for (uint64_t I = 0; I < *Size; ++I) {
@@ -1112,9 +1114,13 @@ std::error_code SampleProfileReaderBinary::readNameTable() {
   bool UseMD5 = useMD5();
 
   NameTable.clear();
+  if (*Size > NameTable.max_size())
+    return sampleprof_error::too_large;
   NameTable.reserve(*Size);
   if (!ProfileIsCS) {
     MD5SampleContextTable.clear();
+    if (*Size > MD5SampleContextTable.max_size())
+      return sampleprof_error::too_large;
     if (UseMD5)
       MD5SampleContextTable.reserve(*Size);
     else
@@ -1157,6 +1163,8 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
       return sampleprof_error::truncated;
 
     NameTable.clear();
+    if (*Size > NameTable.max_size())
+      return sampleprof_error::too_large;
     NameTable.reserve(*Size);
     for (size_t I = 0; I < *Size; ++I) {
       using namespace support;
@@ -1177,6 +1185,8 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
       return EC;
 
     NameTable.clear();
+    if (*Size > NameTable.max_size())
+      return sampleprof_error::too_large;
     NameTable.reserve(*Size);
     if (!ProfileIsCS)
       MD5SampleContextTable.resize(*Size);
@@ -1206,6 +1216,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readCSNameTableSec() {
     return EC;
 
   CSNameTable.clear();
+  if (*Size > CSNameTable.max_size())
+    return sampleprof_error::too_large;
   CSNameTable.reserve(*Size);
   if (ProfileIsCS) {
     // Delay MD5 computation of CS context until they are needed. Use 0 to



More information about the llvm-commits mailing list