From 51b6070aec91b3ac294131fdf2e0663eb4992a42 Mon Sep 17 00:00:00 2001 From: Aleksey Manevich Date: Sat, 30 Jul 2016 15:13:35 +0300 Subject: fix cmdline quoting on --join + move cmdline quoting code to functions --- src/firejail/cmdline.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ src/firejail/join.c | 24 +------- src/firejail/main.c | 104 +--------------------------------- 3 files changed, 150 insertions(+), 125 deletions(-) create mode 100644 src/firejail/cmdline.c diff --git a/src/firejail/cmdline.c b/src/firejail/cmdline.c new file mode 100644 index 000000000..9818f8ffa --- /dev/null +++ b/src/firejail/cmdline.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2014-2016 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "firejail.h" +#include +#include +#include +#include +#include +#include + +int cmdline_length(int argc, char **argv, int index) { + int i,j; + int len = 0; + int argcnt = argc - index; + bool in_quotes = false; + + for (i = 0; i < argcnt; i++) { + in_quotes = false; + for (j = 0; j < strlen(argv[i + index]); j++) { + if (argv[i + index][j] == '\'') { + if (in_quotes) + len++; + if (j > 0 && argv[i + index][j-1] == '\'') + len++; + else + len += 3; + in_quotes = false; + } else { + if (!in_quotes) + len++; + len++; + in_quotes = true; + } + } + if (in_quotes) { + len++; + } + if (strlen(argv[i + index]) == 0) { + len += 2; + } + len++; + } + + return len; +} + +void quote_cmdline(char *command_line, char *window_title, int len, int argc, char **argv, int index) { + int i,j; + int argcnt = argc - index; + bool in_quotes = false; + char *ptr1 = command_line; + char *ptr2 = window_title; + + for (i = 0; i < argcnt; i++) { + + // enclose args by single quotes, + // and since single quote can't be represented in single quoted text + // each occurence of it should be enclosed by double quotes + in_quotes = false; + for (j = 0; j < strlen(argv[i + index]); j++) { + // single quote + if (argv[i + index][j] == '\'') { + if (in_quotes) { + // close quotes + ptr1[0] = '\''; + ptr1++; + } + // previous char was single quote too + if (j > 0 && argv[i + index][j-1] == '\'') { + ptr1--; + sprintf(ptr1, "\'\""); + } + // this first in series + else + { + sprintf(ptr1, "\"\'\""); + } + ptr1 += strlen(ptr1); + in_quotes = false; + } + // anything other + else + { + if (!in_quotes) { + // open quotes + ptr1[0] = '\''; + ptr1++; + } + ptr1[0] = argv[i + index][j]; + ptr1++; + in_quotes = true; + } + } + // close quotes + if (in_quotes) { + ptr1[0] = '\''; + ptr1++; + } + // handle empty argument case + if (strlen(argv[i + index]) == 0) { + sprintf(ptr1, "\'\'"); + ptr1 += strlen(ptr1); + } + // add space + sprintf(ptr1, " "); + ptr1 += strlen(ptr1); + + sprintf(ptr2, "%s ", argv[i + index]); + ptr2 += strlen(ptr2); + } + + assert(len == strlen(command_line)); +} + +void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index) { + int len = cmdline_length(argc, argv, index); + + *command_line = malloc(len + 1); + if (!*command_line) + errExit("malloc"); + *window_title = malloc(len + 1); + if (!*window_title) + errExit("malloc"); + + quote_cmdline(*command_line, *window_title, len, argc, argv, index); + + assert(*command_line); + assert(*window_title); +} diff --git a/src/firejail/join.c b/src/firejail/join.c index c14108986..0b5b6a34a 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c @@ -49,29 +49,9 @@ static void extract_command(int argc, char **argv, int index) { exit(1); } - - int len = 0; - int i; - // calculate command length - for (i = index; i < argc; i++) { - len += strlen(argv[i]) + 3; - } - assert(len > 0); - // build command - cfg.command_line = malloc(len + 1); - *cfg.command_line = '\0'; - for (i = index; i < argc; i++) { - if (strchr(argv[i], '&')) { - strcat(cfg.command_line, "\'"); - strcat(cfg.command_line, argv[i]); - strcat(cfg.command_line, "\' "); - } - else { - strcat(cfg.command_line, argv[i]); - strcat(cfg.command_line, " "); - } - } + build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, index); + if (arg_debug) printf("Extracted command #%s#\n", cfg.command_line); } diff --git a/src/firejail/main.c b/src/firejail/main.c index cbc3d57cf..e86d78ff1 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -2004,109 +2004,7 @@ int main(int argc, char **argv) { cfg.window_title = "appimage"; } else { - // calculate the length of the command - int i; - int len = 0; - int argcnt = argc - prog_index; - int j; - bool in_quotes = false; - - for (i = 0; i < argcnt; i++) { - in_quotes = false; - for (j = 0; j < strlen(argv[i + prog_index]); j++) { - if (argv[i + prog_index][j] == '\'') { - if (in_quotes) - len++; - if (j > 0 && argv[i + prog_index][j-1] == '\'') - len++; - else - len += 3; - in_quotes = false; - } else { - if (!in_quotes) - len++; - len++; - in_quotes = true; - } - } - if (in_quotes) { - len++; - } - if (strlen(argv[i + prog_index]) == 0) { - len += 2; - } - len++; - } - - // build the string - cfg.command_line = malloc(len + 1); // + '\0' - if (!cfg.command_line) - errExit("malloc"); - cfg.window_title = malloc(len + 1); // + '\0' - if (!cfg.window_title) - errExit("malloc"); - - char *ptr1 = cfg.command_line; - char *ptr2 = cfg.window_title; - for (i = 0; i < argcnt; i++) { - - // enclose args by single quotes, - // and since single quote can't be represented in single quoted text - // each occurence of it should be enclosed by double quotes - in_quotes = false; - for (j = 0; j < strlen(argv[i + prog_index]); j++) { - // single quote - if (argv[i + prog_index][j] == '\'') { - if (in_quotes) { - // close quotes - ptr1[0] = '\''; - ptr1++; - } - // previous char was single quote too - if (j > 0 && argv[i + prog_index][j-1] == '\'') { - ptr1--; - sprintf(ptr1, "\'\""); - } - // this first in series - else - { - sprintf(ptr1, "\"\'\""); - } - ptr1 += strlen(ptr1); - in_quotes = false; - } - // anything other - else - { - if (!in_quotes) { - // open quotes - ptr1[0] = '\''; - ptr1++; - } - ptr1[0] = argv[i + prog_index][j]; - ptr1++; - in_quotes = true; - } - } - // close quotes - if (in_quotes) { - ptr1[0] = '\''; - ptr1++; - } - // handle empty argument case - if (strlen(argv[i + prog_index]) == 0) { - sprintf(ptr1, "\'\'"); - ptr1 += strlen(ptr1); - } - // add space - sprintf(ptr1, " "); - ptr1 += strlen(ptr1); - - sprintf(ptr2, "%s ", argv[i + prog_index]); - ptr2 += strlen(ptr2); - } - - assert(len == strlen(cfg.command_line)); + build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index); } assert(cfg.command_name); -- cgit v1.2.3-54-g00ecf