summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Aleksey Manevich <manevich.aleksey@gmail.com>2016-07-19 15:45:55 +0300
committerLibravatar GitHub <noreply@github.com>2016-07-19 15:45:55 +0300
commit1f4e6d3888130eff5485cbdd6ff4e84aa6e69f96 (patch)
tree91e1602e7545d8b377348f703146a6b3d3163c62 /src
parentFix problem with single quotes in args (diff)
downloadfirejail-1f4e6d3888130eff5485cbdd6ff4e84aa6e69f96.tar.gz
firejail-1f4e6d3888130eff5485cbdd6ff4e84aa6e69f96.tar.zst
firejail-1f4e6d3888130eff5485cbdd6ff4e84aa6e69f96.zip
Fix problem with single quotes in args
Single quotes can't be represented in single quoted text, so quote them separately by double quotes. Better version.
Diffstat (limited to 'src')
-rw-r--r--src/firejail/main.c96
1 files changed, 69 insertions, 27 deletions
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 28351a2df..4f1c81e2b 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -2009,25 +2009,34 @@ int main(int argc, char **argv) {
2009 int len = 0; 2009 int len = 0;
2010 int argcnt = argc - prog_index; 2010 int argcnt = argc - prog_index;
2011 int j; 2011 int j;
2012 char *arg, *arg_ptr, *token; 2012 bool in_quotes = false;
2013 2013
2014 for (i = 0; i < argcnt; i++) { 2014 for (i = 0; i < argcnt; i++) {
2015 arg = strdup(argv[i + prog_index]); 2015 in_quotes = false;
2016 arg_ptr = arg; 2016 for (j = 0; j < strlen(argv[i + prog_index]); j++) {
2017 for (token = strsep(&arg_ptr, "\'"); token != NULL; token = strsep(&arg_ptr, "\'")) { 2017 if (argv[i + prog_index][j] == '\'') {
2018 if (token[0] == '\0') { 2018 if (in_quotes)
2019 len += 3; 2019 len++;
2020 if (j > 0 && argv[i + prog_index][j-1] == '\'')
2021 len++;
2022 else
2023 len += 3;
2024 in_quotes = false;
2020 } else { 2025 } else {
2021 len += strlen(token) + 5; 2026 if (!in_quotes)
2027 len++;
2028 len++;
2029 in_quotes = true;
2022 } 2030 }
2023 } 2031 }
2024 free(arg); 2032 if (in_quotes) {
2025 len -= 2; // + ' ' - 3 char overrun 2033 len++;
2034 }
2035 if (strlen(argv[i + prog_index]) == 0) {
2036 len += 2;
2037 }
2038 len++;
2026 } 2039 }
2027 len += 3; // for overrun
2028
2029 if (arg_debug)
2030 printf("Predicted command length %d\n", len);
2031 2040
2032 // build the string 2041 // build the string
2033 cfg.command_line = malloc(len + 1); // + '\0' 2042 cfg.command_line = malloc(len + 1); // + '\0'
@@ -2040,31 +2049,64 @@ int main(int argc, char **argv) {
2040 char *ptr1 = cfg.command_line; 2049 char *ptr1 = cfg.command_line;
2041 char *ptr2 = cfg.window_title; 2050 char *ptr2 = cfg.window_title;
2042 for (i = 0; i < argcnt; i++) { 2051 for (i = 0; i < argcnt; i++) {
2052
2043 // enclose args by single quotes, 2053 // enclose args by single quotes,
2044 // and since single quote can't be represented in single quoted text 2054 // and since single quote can't be represented in single quoted text
2045 // each occurence of it in arg should be enclosed by double quotes 2055 // each occurence of it should be enclosed by double quotes
2046 arg = strdup(argv[i + prog_index]); 2056 in_quotes = false;
2047 arg_ptr = arg; 2057 for (j = 0; j < strlen(argv[i + prog_index]); j++) {
2048 for (token = strsep(&arg_ptr, "\'"); token != NULL; token = strsep(&arg_ptr, "\'")) { 2058 // single quote
2049 if (token[0] == '\0') { 2059 if (argv[i + prog_index][j] == '\'') {
2050 sprintf(ptr1, "\"\'\""); 2060 if (in_quotes) {
2051 } else { 2061 // close quotes
2052 sprintf(ptr1, "\'%s\'\"\'\"", token); 2062 ptr1[0] = '\'';
2063 ptr1++;
2064 }
2065 // previous char was single quote too
2066 if (j > 0 && argv[i + prog_index][j-1] == '\'') {
2067 ptr1--;
2068 sprintf(ptr1, "\'\"");
2069 }
2070 // this first in series
2071 else
2072 {
2073 sprintf(ptr1, "\"\'\"");
2074 }
2075 ptr1 += strlen(ptr1);
2076 in_quotes = false;
2053 } 2077 }
2078 // anything other
2079 else
2080 {
2081 if (!in_quotes) {
2082 // open quotes
2083 ptr1[0] = '\'';
2084 ptr1++;
2085 }
2086 ptr1[0] = argv[i + prog_index][j];
2087 ptr1++;
2088 in_quotes = true;
2089 }
2090 }
2091 // close quotes
2092 if (in_quotes) {
2093 ptr1[0] = '\'';
2094 ptr1++;
2095 }
2096 // handle empty argument case
2097 if (strlen(argv[i + prog_index]) == 0) {
2098 sprintf(ptr1, "\'\'");
2054 ptr1 += strlen(ptr1); 2099 ptr1 += strlen(ptr1);
2055 } 2100 }
2056 free(arg); 2101 // add space
2057 ptr1 -= 3;
2058
2059 sprintf(ptr1, " "); 2102 sprintf(ptr1, " ");
2060 ptr1 += strlen(ptr1); 2103 ptr1 += strlen(ptr1);
2061 2104
2062 sprintf(ptr2, "%s ", argv[i + prog_index]); 2105 sprintf(ptr2, "%s ", argv[i + prog_index]);
2063 ptr2 += strlen(ptr2); 2106 ptr2 += strlen(ptr2);
2064 } 2107 }
2065 ptr1[0]='\0'; // just to be sure 2108
2066 if (arg_debug) 2109 assert(len == strlen(cfg.command_line));
2067 printf("Actual command length %zd\n", strlen(cfg.command_line));
2068 } 2110 }
2069 2111
2070 assert(cfg.command_name); 2112 assert(cfg.command_name);