Origin: https://github.com/sqlite/sqlite/commit/c597ed79d1bd03f57198d10d1f431adda293cf2e
From 1b689bd9118b4df99988e867e36ad25a3e2e22cf Mon Sep 17 00:00:00 2001
From: dan <Dan Kennedy>
Date: Thu, 21 May 2026 14:58:36 +0000
Subject: [PATCH] Fix a buffer overread in the session module that could occur
 when processing a corrupt changeset.

FossilOrigin-Name: 869a51ae84dfaaf824c872e4b3024f35eea7fa67bb584759a2d42ebf8404ef6e
---
 ext/session/sessionC.test    | 25 ++++++++++++++++++++++++-
 ext/session/sqlite3session.c |  6 ++++--
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/ext/session/sessionC.test b/ext/session/sessionC.test
index 79d4b6f..e04073a 100644
--- a/ext/session/sessionC.test
+++ b/ext/session/sessionC.test
@@ -1,4 +1,4 @@
-# 2014 August 16
+# 2014 August 16
 #
 # The author disclaims copyright to this source code.  In place of
 # a legal notice, here is a blessing:
@@ -273,4 +273,27 @@ do_test 7.0 {
 } {1 SQLITE_CORRUPT}
 grp delete
 
+#-------------------------------------------------------------------------
+#
+reset_db
+set CS 54014f300009ff
+
+do_test 8.0 {
+  sqlite3changegroup grp
+  list [catch { grp add [db one {SELECT unhex($CS)}] } msg] $msg
+} {1 SQLITE_CORRUPT}
+grp delete
+
+#-------------------------------------------------------------------------
+#
+reset_db
+set CS 540101740017000003ffffffff
+
+do_test 9.0 {
+  set C [db one {SELECT unhex($CS)}]
+  list [catch { sqlite3changeset_concat $C $C } msg] $msg
+} {1 SQLITE_CORRUPT}
+
 finish_test
+
+
diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c
index cba81d5..e12e32c 100644
--- a/ext/session/sqlite3session.c
+++ b/ext/session/sqlite3session.c
@@ -346,7 +346,9 @@ static int sessionVarintLen(int iVal){
 ** bytes read.
 */
 static int sessionVarintGet(const u8 *aBuf, int *piVal){
-  return getVarint32(aBuf, *piVal);
+  int ret = getVarint32(aBuf, *piVal);
+  *piVal = (*piVal & 0x7FFFFFFF);
+  return ret;
 }
 
 /*
@@ -361,7 +363,7 @@ static int sessionVarintGetSafe(const u8 *aBuf, int nBuf, int *piVal){
     memcpy(aCopy, aBuf, nBuf);
     aRead = aCopy;
   }
-  return getVarint32(aRead, *piVal);
+  return sessionVarintGet(aRead, piVal);
 }
 
 /* Load an unaligned and unsigned 32-bit integer */