From cd0ecd4e9621ad6ee55fda908c4fb1366bae8028 Mon Sep 17 00:00:00 2001
From: terencehill <piuntn@gmail.com>
Date: Wed, 7 Feb 2024 22:40:06 +0100
Subject: [PATCH] Fix REGISTRY_CHECK not checking all elements of a huge
 registry like the Notifications registry

Code is optimized to have basically the same performance as before while adding string length checks.
---
 qcsrc/lib/registry.qh | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/qcsrc/lib/registry.qh b/qcsrc/lib/registry.qh
index fdcc730a06..5d36e1a393 100644
--- a/qcsrc/lib/registry.qh
+++ b/qcsrc/lib/registry.qh
@@ -177,8 +177,25 @@ void Registry_send(string id, string hash);
 	STATIC_INIT(Registry_check_##id) \
 	{ \
 		/* Note: SHA256 isn't always available, use MD4 instead */ \
-		string s = ""; \
-		FOREACH(id, true, s = strcat(s, ":", it.registered_id)); \
+		string s = "", group = ""; \
+		int str_len = 0, digests_len = 0, group_idx = 0; \
+		FOREACH(id, true, { \
+			group = strcat(group, ":", it.registered_id); \
+			if (++group_idx < 50) /* this is to reduce strlen calls */ \
+				continue; \
+			int group_len = strlen(group); \
+			if (str_len + 1 + group_len >= 16383) /* exceeding max string length? */ \
+			{ \
+				/* keep previous digests and replace current string with its digest */ \
+				s = strcat(substring(s, 0, digests_len), ":", digest_hex("MD4", s)); \
+				digests_len = str_len = strlen(s); \
+			} \
+			s = strcat(s, group); \
+			str_len += group_len; \
+			group = ""; \
+			group_idx = 0; \
+		}); \
+		s = strcat(s, group); \
 		s = substring(s, 1, -1); /* remove initial ":" */ \
 		string h = REGISTRY_HASH(id) = strzone(digest_hex("MD4", s)); \
 		LOG_DEBUGF(#id ": %s\n[%s]", h, s); \
-- 
2.39.5