summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2020-09-01 13:14:35 +0300
committerPanu Matilainen <pmatilai@redhat.com>2020-12-10 13:28:07 +0200
commit24c10a49078e679d7ccf3f1d4fe656d4e5f2c1f0 (patch)
tree1baa38300ec82b51b7f1323fd6cb92eb9ea83445
parent7d0c224f2fbde64161a440fb93f18f5736403a70 (diff)
downloadrpm-24c10a49078e679d7ccf3f1d4fe656d4e5f2c1f0.tar.gz
Fix possible read beyond buffer in rstrnlenhash()
On strings that are not \0-terminated (which are a big reason for the existence of this function), the while-loop would try to compare the first character beyond the specified buffer for '\0' before realizing we're already beyond the end when checking n. Should be mostly harmless in practise as the check for n would still terminate it, but not right. In particular this trips up address sanitizer with the bdb backend where some of the returned strings are not \0-terminated. Test for string length first, and move the decrementing side-effect into the loop for better readability. (cherry picked from commit 747b7119ae89a3ccaceeae4f5570c7ab83d2cf5d)
-rw-r--r--rpmio/rpmstrpool.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/rpmio/rpmstrpool.c b/rpmio/rpmstrpool.c
index 776ca6dea..0db0b5313 100644
--- a/rpmio/rpmstrpool.c
+++ b/rpmio/rpmstrpool.c
@@ -88,11 +88,12 @@ static inline unsigned int rstrnlenhash(const char * str, size_t n, size_t * len
unsigned int hash = 0xe4721b68;
const char * s = str;
- while (*s != '\0' && n-- > 0) {
+ while (n > 0 && *s != '\0') {
hash += *s;
hash += (hash << 10);
hash ^= (hash >> 6);
s++;
+ n--;
}
hash += (hash << 3);
hash ^= (hash >> 11);