Repository: alacritty/alacritty
File: alacritty_terminal/src/ansi.rs (Rust)

Code before:
                            continue;
                        },
                    };

                    if let Some(c) = xparse_color(chunk[1]) {
                        self.handler.set_color(index as usize, c);
                    } else if chunk[1] == b"?" {
                        let prefix = format!("4;{index}");
                        self.handler.dynamic_color_sequence(prefix, index as usize, terminator);
                    } else {
                        unhandled(params);
                    }
                }
            },

            // Hyperlink.
            b"8" if params.len() > 2 => {
                let link_params = params[1];
                let mut uri = str::from_utf8(params[2]).unwrap_or_default().to_string();
                // XXX The escape sequence is of form 'OSC 8 ; params ; URI ST, where
                // URI is URL-encoded, however `;` is a special character and might be
                // passed as is, thus we should rebuild the URI.
                for param in params[3..].iter() {
                    uri.push(';');
                    uri.push_str(str::from_utf8(param).unwrap_or_default());
                }

                // The OSC 8 escape sequence must be stopped when getting an empty `uri`.
                if uri.is_empty() {
                    self.handler.set_hyperlink(None);
                    return;
                }

                // Link parameters are in format of `key1=value1:key2=value2`. Currently only key
                // `id` is defined.
                let id = link_params
                    .split(|&b| b == b':')
                    .find_map(|kv| kv.strip_prefix(b"id="))
                    .and_then(|kv| str::from_utf8(kv).ok());

                self.handler.set_hyperlink(Some(Hyperlink::new(id, uri)));
            },

            // Get/set Foreground, Background, Cursor colors.
            b"10" | b"11" | b"12" => {
                if params.len() >= 2 {
                    if let Some(mut dynamic_code) = parse_number(params[0]) {
                        for param in &params[1..] {
                            // 10 is the first dynamic color, also the foreground.
                            let offset = dynamic_code as usize - 10;
                            let index = NamedColor::Foreground as usize + offset;

Review comment (security):
```suggestion

                // NOTE: The escape sequence is of form 'OSC 8 ; params ; URI ST', where
                // URI is URL-encoded. However `;` is a special character and might be
                // passed as is, thus we need to rebuild the URI.
                let mut uri = str::from_utf8(params[2]).unwrap_or_default().to_string();
                for param in params[3..].iter() {
                    uri.push(';');
                    uri.push_str(str::from_utf8(param).unwrap_or_default());
                }
```

Code after:
                            continue;
                        },
                    };

                    if let Some(c) = xparse_color(chunk[1]) {
                        self.handler.set_color(index as usize, c);
                    } else if chunk[1] == b"?" {
                        let prefix = format!("4;{index}");
                        self.handler.dynamic_color_sequence(prefix, index as usize, terminator);
                    } else {
                        unhandled(params);
                    }
                }
            },

            // Hyperlink.
            b"8" if params.len() > 2 => {
                let link_params = params[1];

                // NOTE: The escape sequence is of form 'OSC 8 ; params ; URI ST', where
                // URI is URL-encoded. However `;` is a special character and might be
                // passed as is, thus we need to rebuild the URI.
                let mut uri = str::from_utf8(params[2]).unwrap_or_default().to_string();
                for param in params[3..].iter() {
                    uri.push(';');
                    uri.push_str(str::from_utf8(param).unwrap_or_default());
                }

                // The OSC 8 escape sequence must be stopped when getting an empty `uri`.
                if uri.is_empty() {
                    self.handler.set_hyperlink(None);
                    return;
                }

                // Link parameters are in format of `key1=value1:key2=value2`. Currently only key
                // `id` is defined.
                let id = link_params
                    .split(|&b| b == b':')
                    .find_map(|kv| kv.strip_prefix(b"id="))
                    .and_then(|kv| str::from_utf8(kv).ok());

                self.handler.set_hyperlink(Some(Hyperlink::new(id, uri)));
            },

            // Get/set Foreground, Background, Cursor colors.
            b"10" | b"11" | b"12" => {
                if params.len() >= 2 {
                    if let Some(mut dynamic_code) = parse_number(params[0]) {
                        for param in &params[1..] {
                            // 10 is the first dynamic color, also the foreground.
                            let offset = dynamic_code as usize - 10;