bug#78507: [Security] Heap Buffer Overflow in GNU Coreutils sort (CWE-122)

Pádraig Brady <[email protected]>
Newsgroups gmane.comp.gnu.core-utils.bugs
Message-ID <[email protected]>
On 20/05/2025 16:15, Pádraig Brady wrote:
> Indeed. I introduced this in coreutils 7.2 (2009).
> One can repro on Fedora for e.g. with:
> 
> _POSIX2_VERSION=200809 LC_ALL=C valgrind sort +0.18446744073709551615R poc_input.txt
> ==984625== Memcheck, a memory error detector
> ==984625== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info
> ==984625== Command: sort +0.18446744073709551615R poc_input.txt
> ==984625==
> ==984625== Invalid read of size 1
> 
> Going back to the more verbose code from coreutils 7.1 avoids the issue.
> I'll test a bit more here and post a full patch in a while.

The attached patch addresses the issue here,
and includes a test verified to trigger with ASAN or valgrind available.
I'll push this later.

thanks,
Pádraig
sort-under-read.patch (text/x-patch, 3.5 KB)
From 462dbab3b223c4076e5bf90455c02cb53d38ef23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Tue, 20 May 2025 16:03:44 +0100
Subject: [PATCH] sort: fix buffer under-read (CWE-127)

* src/sort.c (begfield): Check pointer adjustment
to avoid Out-of-range pointer offset (CWE-823).
(limfield): Likewise.
* tests/sort/sort-field-limit.sh: Add a new test,
which triggers with ASAN or Valgrind.
* tests/local.mk: Reference the new test.
* NEWS: Mention bug fix introduced in v7.2 (2009).
Fixes https://bugs.gnu.org/78507
---
 src/sort.c                     | 12 ++++++++++--
 tests/local.mk                 |  1 +
 tests/sort/sort-field-limit.sh | 35 ++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 2 deletions(-)
 create mode 100755 tests/sort/sort-field-limit.sh

diff --git a/src/sort.c b/src/sort.c
index b10183b6f..7af1a2512 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -1644,7 +1644,11 @@ begfield (struct line const *line, struct keyfield const *key)
       ++ptr;
 
   /* Advance PTR by SCHAR (if possible), but no further than LIM.  */
-  ptr = MIN (lim, ptr + schar);
+  size_t remaining_bytes = lim - ptr;
+  if (schar < remaining_bytes)
+    ptr += schar;
+  else
+    ptr = lim;
 
   return ptr;
 }
@@ -1746,7 +1750,11 @@ limfield (struct line const *line, struct keyfield const *key)
           ++ptr;
 
       /* Advance PTR by ECHAR (if possible), but no further than LIM.  */
-      ptr = MIN (lim, ptr + echar);
+      size_t remaining_bytes = lim - ptr;
+      if (echar < remaining_bytes)
+        ptr += echar;
+      else
+        ptr = lim;
     }
 
   return ptr;
diff --git a/tests/local.mk b/tests/local.mk
index 4da6756ac..642d225fa 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -388,6 +388,7 @@ all_tests =					\
   tests/sort/sort-debug-keys.sh			\
   tests/sort/sort-debug-warn.sh			\
   tests/sort/sort-discrim.sh			\
+  tests/sort/sort-field-limit.sh		\
   tests/sort/sort-files0-from.pl		\
   tests/sort/sort-float.sh			\
   tests/sort/sort-h-thousands-sep.sh		\
diff --git a/tests/sort/sort-field-limit.sh b/tests/sort/sort-field-limit.sh
new file mode 100755
index 000000000..300d35806
--- /dev/null
+++ b/tests/sort/sort-field-limit.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# From 7.2-9.7, this would trigger an out of bounds mem read
+
+# Copyright (C) 2025 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ sort
+getlimits_
+
+# This issue triggers with valgrind or ASAN
+valgrind --error-exitcode=1 true 2>/dev/null &&
+  VALGRIND='valgrind --error-exitcode=1'
+
+{ printf '%s\n' aa bb; } > in || framework_failure_
+
+_POSIX2_VERSION=200809 $VALGRIND sort +0.${SIZE_MAX}R in > out || fail=1
+compare in out || fail=1
+
+_POSIX2_VERSION=200809 $VALGRIND sort +1 -1.${SIZE_MAX}R in > out || fail=1
+compare in out || fail=1
+
+Exit $fail
-- 
2.49.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.