From 51de74d5201b0a1e314ed24cb1003dc3cf701633 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 19 Nov 2018 13:28:52 +0100 Subject: [PATCH] luci-base: further hash calculation signedness bugfixes - cbi.js: make sure to treat single bytes as signed char when handling end cases - template_lmo.c: make sure to treat single bytes as signed char when handling end cases, avoids hash miscalculations on ARM Signed-off-by: Jo-Philipp Wich --- .../htdocs/luci-static/resources/cbi.js | 21 +++++++++++++------ modules/luci-base/src/template_lmo.c | 4 ++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/modules/luci-base/htdocs/luci-static/resources/cbi.js b/modules/luci-base/htdocs/luci-static/resources/cbi.js index 0e9590681..1607b9af6 100644 --- a/modules/luci-base/htdocs/luci-static/resources/cbi.js +++ b/modules/luci-base/htdocs/luci-static/resources/cbi.js @@ -15,6 +15,15 @@ var cbi_d = []; var cbi_t = []; var cbi_strings = { path: {}, label: {} }; +function s8(bytes, off) { + var n = bytes[off]; + return (n > 0x7F) ? (n - 256) >>> 0 : n; +} + +function u16(bytes, off) { + return ((bytes[off + 1] << 8) + bytes[off]) >>> 0; +} + function sfh(s) { if (s === null || s.length === 0) return null; @@ -48,8 +57,8 @@ function sfh(s) { off = 0, tmp; while (len--) { - hash += ((bytes[off + 1] << 8) + bytes[off]) >>> 0; - tmp = ((((bytes[off + 3] << 8) + bytes[off + 2]) << 11) ^ hash) >>> 0; + hash += u16(bytes, off); + tmp = ((u16(bytes, off + 2) << 11) ^ hash) >>> 0; hash = ((hash << 16) ^ tmp) >>> 0; hash += hash >>> 11; off += 4; @@ -57,20 +66,20 @@ function sfh(s) { switch ((bytes.length & 3) >>> 0) { case 3: - hash += ((bytes[off + 1] << 8) + bytes[off]) >>> 0; + hash += u16(bytes, off); hash = (hash ^ (hash << 16)) >>> 0; - hash = (hash ^ (bytes[off + 2] << 18)) >>> 0; + hash = (hash ^ (s8(bytes, off + 2) << 18)) >>> 0; hash += hash >>> 11; break; case 2: - hash += ((bytes[off + 1] << 8) + bytes[off]) >>> 0; + hash += u16(bytes, off); hash = (hash ^ (hash << 11)) >>> 0; hash += hash >>> 17; break; case 1: - hash += bytes[off]; + hash += s8(bytes, off); hash = (hash ^ (hash << 10)) >>> 0; hash += hash >>> 1; break; diff --git a/modules/luci-base/src/template_lmo.c b/modules/luci-base/src/template_lmo.c index cd4c609a7..f7a118c9b 100644 --- a/modules/luci-base/src/template_lmo.c +++ b/modules/luci-base/src/template_lmo.c @@ -46,14 +46,14 @@ uint32_t sfh_hash(const char *data, int len) switch (rem) { case 3: hash += sfh_get16(data); hash ^= hash << 16; - hash ^= data[sizeof(uint16_t)] << 18; + hash ^= (signed char)data[sizeof(uint16_t)] << 18; hash += hash >> 11; break; case 2: hash += sfh_get16(data); hash ^= hash << 11; hash += hash >> 17; break; - case 1: hash += *data; + case 1: hash += (signed char)*data; hash ^= hash << 10; hash += hash >> 1; } -- 2.25.1