From owner-freebsd-bugs Tue May 21 5:40:39 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 60CDC37B40D for ; Tue, 21 May 2002 05:40:02 -0700 (PDT) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g4LCe2d48368; Tue, 21 May 2002 05:40:02 -0700 (PDT) (envelope-from gnats) Received: from melchior.cuivre.fr.eu.org (melchior.enst.fr [137.194.161.6]) by hub.freebsd.org (Postfix) with ESMTP id 8CB9F37B401 for ; Tue, 21 May 2002 05:35:51 -0700 (PDT) Received: from melusine.cuivre.fr.eu.org (melusine.enst.fr [137.194.160.34]) by melchior.cuivre.fr.eu.org (Postfix) with ESMTP id 9CC497A49 for ; Tue, 21 May 2002 14:35:48 +0200 (CEST) Received: by melusine.cuivre.fr.eu.org (Postfix, from userid 1000) id 6EAB62C3D1; Tue, 21 May 2002 14:35:47 +0200 (CEST) Message-Id: <20020521123547.6EAB62C3D1@melusine.cuivre.fr.eu.org> Date: Tue, 21 May 2002 14:35:47 +0200 (CEST) From: Thomas Quinot Reply-To: Thomas Quinot To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: bin/38374: [patch] crontab environment variable parsing is broken Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 38374 >Category: bin >Synopsis: [patch] crontab environment variable parsing is broken >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue May 21 05:40:02 PDT 2002 >Closed-Date: >Last-Modified: >Originator: Thomas Quinot >Release: FreeBSD 4.5-STABLE i386 >Organization: >Environment: System: FreeBSD melusine.cuivre.fr.eu.org 4.5-STABLE FreeBSD 4.5-STABLE #36: Sun Apr 28 22:12:31 CEST 2002 thomas@melusine.cuivre.fr.eu.org:/usr2/obj/usr2/src/sys/MELUSINE i386 >Description: load_env(), the function that attempts to parse a crontab line as an environment variable assignment, is broken and not conformant to its description in the manual page. >How-To-Repeat: First: ------ Make a /etc/crontab entry containing *****PATH=/some/path some_command (note that there are no spaces before the '=' sign). Note (using cron -x pars) that load_env will incorrectly report success parsing that line as a variable assignment. Note (looking at /var/log/cron) that this line has not been parsed as a command entry, and that some_command is never executed. >Fix: Here is a proposed solution. Index: env.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/cron/lib/env.c,v retrieving revision 1.7.2.1 diff -u -r1.7.2.1 env.c --- env.c 1 Jul 2000 10:35:07 -0000 1.7.2.1 +++ env.c 21 May 2002 12:33:52 -0000 @@ -144,7 +144,18 @@ long filepos; int fileline; char name[MAX_ENVSTR], val[MAX_ENVSTR]; - int fields; + char quotechar, *c, *str; + int state; + + /* The following states are traversed in order: */ +#define NAMEI 0 /* First char of NAME, may be quote */ +#define NAME 1 /* Subsequent chars of NAME */ +#define EQ1 2 /* After end of name, looking for '=' sign */ +#define EQ2 3 /* After '=', skipping whitespace */ +#define VALUEI 4 /* First char of VALUE, may be quote */ +#define VALUE 5 /* Subsequent chars of VALUE */ +#define FINI 6 /* All done, skipping trailing whitespace */ +#define ERROR 7 /* Error */ filepos = ftell(f); fileline = LineNumber; @@ -152,35 +163,77 @@ if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n")) return (ERR); - Debug(DPARS, ("load_env, read <%s>\n", envstr)) + Debug(DPARS, ("load_env, read <%s>\n", envstr)); - name[0] = val[0] = '\0'; - fields = sscanf(envstr, "%[^ =] = %[^\n#]", name, val); - if (fields != 2) { - Debug(DPARS, ("load_env, not 2 fields (%d)\n", fields)) + bzero (name, sizeof name); + bzero (val, sizeof val); + str = name; + state = NAMEI; + quotechar = '\0'; + c = envstr; + while (state != ERROR && *c) { + switch (state) { + case NAMEI: + case VALUEI: + if (*c == '\'' || *c == '"') + quotechar = *c++; + ++state; + /* FALLTHROUGH */ + case NAME: + case VALUE: + if (quotechar) { + if (*c == quotechar) { + state++; + c++; + break; + } + if (state == NAME && *c == '=') { + state = ERROR; + break; + } + } else { + if (isspace (*c)) { + state++; + c++; + break; + } + if (state == NAME && *c == '=') { + state++; + break; + } + } + *str++ = *c++; + break; + + case EQ1: + if (*c == '=') { + state++; + str = val; + quotechar = '\0'; + } else { + if (!isspace (*c)) + state = ERROR; + } + c++; + break; + case EQ2: + case FINI: + if (isspace (*c)) + c++; + else + state++; + break; + } + } + if (state != FINI && !(state == VALUE && !quotechar)) { + Debug(DPARS, ("load_env, parse error, state = %d\n", state)) fseek(f, filepos, 0); Set_LineNum(fileline); return (FALSE); } - /* 2 fields from scanf; looks like an env setting - */ - - /* - * process value string + /* 2 fields from parser; looks like an env setting */ - /*local*/{ - int len = strdtb(val); - - if (len >= 2) { - if (val[0] == '\'' || val[0] == '"') { - if (val[len-1] == val[0]) { - val[len-1] = '\0'; - (void) strcpy(val, val+1); - } - } - } - } if (strlen(name) + 1 + strlen(val) >= MAX_ENVSTR-1) return (FALSE); >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message