This is an automated email from the ASF dual-hosted git repository.
hgruszecki pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/master by this push:
new 3887d1801 fix(server): handle empty permission maps in serialization
(#2527)
3887d1801 is described below
commit 3887d18017da16e5706b97b428d492e3c59becdb
Author: Hubert Gruszecki <[email protected]>
AuthorDate: Tue Dec 30 13:04:17 2025 +0100
fix(server): handle empty permission maps in serialization (#2527)
Permissions::to_bytes() wrote has_streams=1 or has_topics=1 for
Some(empty_map) but the for loop never executed, leaving no data
or terminator. On deserialization, from_bytes() entered a loop
expecting stream/topic data and panicked with "advance out of
bounds" when calling get_u32_le() on an empty buffer. This caused
server crashes on restart when users were created via web UI with
empty permission maps. The fix filters out empty maps at the
pattern match level, treating them as None during serialization.
---
Cargo.lock | 2 +-
DEPENDENCIES.md | 2 +-
.../src/types/permissions/permissions_global.rs | 42 ++++++++++++++++++++--
core/server/Cargo.toml | 2 +-
4 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index e83635af0..0f92b7d98 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8239,7 +8239,7 @@ dependencies = [
[[package]]
name = "server"
-version = "0.6.1-edge.1"
+version = "0.6.1-edge.2"
dependencies = [
"ahash 0.8.12",
"anyhow",
diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md
index 9a17781d1..c00dd4aa0 100644
--- a/DEPENDENCIES.md
+++ b/DEPENDENCIES.md
@@ -725,7 +725,7 @@ serde_with_macros: 3.16.1, "Apache-2.0 OR MIT",
serde_yaml_ng: 0.10.0, "MIT",
serial_test: 3.2.0, "MIT",
serial_test_derive: 3.2.0, "MIT",
-server: 0.6.1-edge.1, "Apache-2.0",
+server: 0.6.1-edge.2, "Apache-2.0",
sha1: 0.10.6, "Apache-2.0 OR MIT",
sha2: 0.10.9, "Apache-2.0 OR MIT",
sha3: 0.10.8, "Apache-2.0 OR MIT",
diff --git a/core/common/src/types/permissions/permissions_global.rs
b/core/common/src/types/permissions/permissions_global.rs
index 8291d48f9..bc3f29382 100644
--- a/core/common/src/types/permissions/permissions_global.rs
+++ b/core/common/src/types/permissions/permissions_global.rs
@@ -232,7 +232,7 @@ impl BytesSerializable for Permissions {
bytes.put_u8(if self.global.read_topics { 1 } else { 0 });
bytes.put_u8(if self.global.poll_messages { 1 } else { 0 });
bytes.put_u8(if self.global.send_messages { 1 } else { 0 });
- if let Some(streams) = &self.streams {
+ if let Some(streams) = self.streams.as_ref().filter(|s| !s.is_empty())
{
bytes.put_u8(1);
let streams_count = streams.len();
let mut current_stream = 1;
@@ -244,7 +244,7 @@ impl BytesSerializable for Permissions {
bytes.put_u8(if stream.read_topics { 1 } else { 0 });
bytes.put_u8(if stream.poll_messages { 1 } else { 0 });
bytes.put_u8(if stream.send_messages { 1 } else { 0 });
- if let Some(topics) = &stream.topics {
+ if let Some(topics) = stream.topics.as_ref().filter(|t|
!t.is_empty()) {
bytes.put_u8(1);
let topics_count = topics.len();
let mut current_topic = 1;
@@ -542,4 +542,42 @@ mod tests {
assert_eq!(permissions, deserialized_permissions);
}
+
+ #[test]
+ fn should_handle_empty_streams_map() {
+ let permissions = Permissions {
+ global: GlobalPermissions::default(),
+ streams: Some(AHashMap::new()),
+ };
+
+ let bytes = permissions.to_bytes();
+ let deserialized = Permissions::from_bytes(bytes).unwrap();
+
+ assert!(deserialized.streams.is_none());
+ }
+
+ #[test]
+ fn should_handle_empty_topics_map() {
+ let permissions = Permissions {
+ global: GlobalPermissions::default(),
+ streams: Some(AHashMap::from([(
+ 1,
+ StreamPermissions {
+ manage_stream: true,
+ read_stream: true,
+ manage_topics: false,
+ read_topics: false,
+ poll_messages: false,
+ send_messages: false,
+ topics: Some(AHashMap::new()),
+ },
+ )])),
+ };
+
+ let bytes = permissions.to_bytes();
+ let deserialized = Permissions::from_bytes(bytes).unwrap();
+
+ let stream = deserialized.streams.as_ref().unwrap().get(&1).unwrap();
+ assert!(stream.topics.is_none());
+ }
}
diff --git a/core/server/Cargo.toml b/core/server/Cargo.toml
index 6ac146fea..41c7d88b0 100644
--- a/core/server/Cargo.toml
+++ b/core/server/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "server"
-version = "0.6.1-edge.1"
+version = "0.6.1-edge.2"
edition = "2024"
license = "Apache-2.0"