Skip to content

Conversation

@emanuele6
Copy link
Contributor

@emanuele6 emanuele6 commented Feb 15, 2022

..instead of injecting them in the output between a pair of '"' charcters.

This prevents windows with a " character in their class or instance name (e.g. urxvt -name 'quote "'), or desktop and monitors with " character in their name from generating invalid or "malicious" JSON.

The main problems that this was causing were:

  • JSON tools like jq were not able to parse the JSON output of "query -T" and "wm -d";

  • if the JSON was invalid (e.g. one extra quote or \ at the end of desktop name), bspwm would not adopt orphans after a "wm -r" command.

  • if the arbitrary strings contained JSON code: e.g.

    bspc desktop -n '","name":"hello'

    the JSON will be interpreted by bspwm after a reload. (in the example above, that desktop will be renamed to "hello" after a reload.)

@emanuele6
Copy link
Contributor Author

emanuele6 commented Feb 15, 2022

This patch simply prints all the (C locale) control characters as \u00XX and adds a backslash in front of \ and " characters, some of the control characters (but not all) have special sequences in JSON: e.g. \n, \t, etc.

JSON string syntax diagram from json.org

json-string-white

We could print these special sequences when possible if we want, but it is not necessary. (passing the JSON through jq will convert them automatically.)

Here is a possible implementation if we want to do it:

#define SPECIAL_SEQUENCE(f, c, json) \
	case c: \
		fputs(json, f); \
		continue;
void print_string_as_json(FILE *f, char *str)
{
	fputc('"', f);
	for (char *ptr = str; *ptr != '\0'; ++ptr) {
		switch (*ptr) {
			SPECIAL_SEQUENCE(f, '"', "\\\"")
			SPECIAL_SEQUENCE(f, '\\', "\\\\")
			SPECIAL_SEQUENCE(f, '\b', "\\b")
			SPECIAL_SEQUENCE(f, '\f', "\\f")
			SPECIAL_SEQUENCE(f, '\n', "\\n")
			SPECIAL_SEQUENCE(f, '\r', "\\r")
			SPECIAL_SEQUENCE(f, '\t', "\\t")
		}
		if (*ptr == '\x7f' || (*ptr >= '\x01' && *ptr <= '\x1f')) {
			fprintf(f, "\\u%04x", *ptr);
			continue;
		}
		fputc(*ptr, f);
	}
	fputc('"', f);
}
#undef SPECIAL_SEQUENCE

..instead of injecting them in the output between a pair of `"`
charcters.

This prevents windows with a `"` character in their class or instance
name, or desktop and monitors with `"` character in their name from
generating invalid or "malicious" JSON.

The main problems that this was causing were:
* JSON tools like jq were not able to parse the JSON output of
  "query -T" and "wm -d";
* if the JSON was invalid (e.g. one extra quote or `\` at the end of
  desktop name), bspwm would not adopt orphans after a "wm -r" command;
* if the arbitrary strings contained JSON code: e.g.

    bspc desktop -n '","name":"hello'

  the JSON will be interpreted by bspwm after a reload. (in the example
  above, that desktop will be renamed to "hello" after a reload.)
@emanuele6
Copy link
Contributor Author

emanuele6 commented Mar 1, 2022

I just realised that bspwm is loading back the json strings by copying the bytes between the starting and ending quotes. that should also be changed otherwise these backslash sequences will not be expanded and restarts will cause bspwm to e.g. rename desktops from desktop "1" to desktop \"1\" to desktop \\\"1\\\" to desktop \\\\\\\"1\\\\\\\" and so on

@emanuele6 emanuele6 marked this pull request as draft October 26, 2023 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant