From 4b1e0a30b8ecf6b45da880e51b29a2d933c418a7 Mon Sep 17 00:00:00 2001 From: Peter Siegel <33677897+yeetypete@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:30:23 +0200 Subject: [PATCH] dev_container: Parse env vars and docker labels with `=` in values correctly (#53134) Fixes a parsing issue where docker env var key/value pairs can contain an "=" character in the value. This is pretty common and present in all [nvidia/cuda](https://hub.docker.com/r/nvidia/cuda) docker images. Also adds some tests for env var parsing. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed a parsing failure where docker env var key/value pairs can contain an "=" character in the value. --- crates/dev_container/src/docker.rs | 57 ++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/crates/dev_container/src/docker.rs b/crates/dev_container/src/docker.rs index e0eecd1da0e2b1749ffcf60fa67cdbef273fda12..88600e2b2a5221165b6ca80e36c0ebcfdf35013a 100644 --- a/crates/dev_container/src/docker.rs +++ b/crates/dev_container/src/docker.rs @@ -56,12 +56,11 @@ impl DockerInspectConfig { pub(crate) fn env_as_map(&self) -> Result, DevContainerError> { let mut map = HashMap::new(); for env_var in &self.env { - let parts: Vec<&str> = env_var.split("=").collect(); - if parts.len() != 2 { - log::error!("Unable to parse {env_var} into and environment key-value"); + let Some((key, value)) = env_var.split_once('=') else { + log::error!("Unable to parse {env_var} into an environment key-value"); return Err(DevContainerError::DevContainerParseFailed); - } - map.insert(parts[0].to_string(), parts[1].to_string()); + }; + map.insert(key.to_string(), value.to_string()); } Ok(map) } @@ -428,12 +427,8 @@ where values .iter() .filter_map(|v| { - let parts: Vec<&str> = v.split("=").collect(); - if parts.len() != 2 { - None - } else { - Some((parts[0].to_string(), parts[1].to_string())) - } + let (key, value) = v.split_once('=')?; + Some((key.to_string(), value.to_string())) }) .collect(), )) @@ -547,6 +542,46 @@ mod test { }, }; + #[test] + fn should_parse_simple_env_var() { + let config = super::DockerInspectConfig { + labels: super::DockerConfigLabels { metadata: None }, + image_user: None, + env: vec!["KEY=value".to_string()], + }; + + let map = config.env_as_map().unwrap(); + assert_eq!(map.get("KEY").unwrap(), "value"); + } + + #[test] + fn should_parse_env_var_with_equals_in_value() { + let config = super::DockerInspectConfig { + labels: super::DockerConfigLabels { metadata: None }, + image_user: None, + env: vec!["COMPLEX=key=val other>=1.0".to_string()], + }; + + let map = config.env_as_map().unwrap(); + assert_eq!(map.get("COMPLEX").unwrap(), "key=val other>=1.0"); + } + + #[test] + fn should_parse_simple_label() { + let json = r#"{"volumes": [], "labels": ["com.example.key=value"]}"#; + let service: DockerComposeService = serde_json_lenient::from_str(json).unwrap(); + let labels = service.labels.unwrap(); + assert_eq!(labels.get("com.example.key").unwrap(), "value"); + } + + #[test] + fn should_parse_label_with_equals_in_value() { + let json = r#"{"volumes": [], "labels": ["com.example.key=value=with=equals"]}"#; + let service: DockerComposeService = serde_json_lenient::from_str(json).unwrap(); + let labels = service.labels.unwrap(); + assert_eq!(labels.get("com.example.key").unwrap(), "value=with=equals"); + } + #[test] fn should_create_docker_inspect_command() { let docker = Docker::new("docker");