2006-04-11 21:52:54 +00:00
|
|
|
/*
|
2007-04-11 08:12:51 +00:00
|
|
|
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
|
|
|
* NOVELL (All rights reserved)
|
2006-04-11 21:52:54 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
|
|
* License published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* 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, contact Novell, Inc.
|
|
|
|
*/
|
|
|
|
|
2014-04-07 03:16:50 -07:00
|
|
|
#include <assert.h>
|
2010-07-31 16:00:52 -07:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
2006-04-11 21:52:54 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
2010-07-31 16:00:52 -07:00
|
|
|
#include <linux/limits.h>
|
|
|
|
|
parser: convert var expansion to use alternations
This patch converts the parser's variable expansion from adding new
entries for each additional variable value to incorporating an
alternation that includes all the values for the variable; e.g. given:
@{BINS}=/bin /usr/bin /sbin /usr/sbin
@{BINS}/binary ix,
rather than expanding to exntries for
/bin/binary
/usr/bin/binary
/sbin/binary
/usr/sbin/binary
one entry would remain that looks like:
{/bin,/usr/bin,/sbin,/usr/sbin}/binary
One complication with this patch is that we try to prevent mistakes for
our users with variable expansion around '/'s; it's common for people to
write profiles that contain things like:
@{BAR}=/bingo/*/ /bango/
/foo/@{BAR}/baz
We already have a post-processing step that walks entries looking
for multiple sequences of '/'s and filters them into single
'/' which worked when creating new entries for each variable
expansion. Converting to alternation expansion breaks this filtering,
so code is added that removes leading and trailing slashes in variable
values in the expansion if the character immediately preceding or
following the variable is also a slash.
The intent behind this is to reduce the amount of memory allocations
and structure walking that needed to occur in when converting from the
entry strings to the back end nodes. Examples with real world profiles
showed performance improvements ranging from 2.5% to 10%. However,
because the back end operations are sensitive to the front end inputs,
it is possible for worse results to occur; for example, it takes the
simple_tests/vars/vars_stress_0[123].sd tests significantly longer to
complete after this patch is applied (vars_stress_03.sd in particular
takes ~23 times longer). An initial analysis of profiling output in
this negative case looks like it causes the tree simplification in
the back end to do more work for unknown reasons.
On the other hand, the test simple_tests/vars/vars_dbus_9.sd
(introduced in "[patch 09/12] parser: more dbus variable testcases")
takes ~1 sec to complete on my laptop before this patch, and roughly
0.01s with this patch applied.
(One option would be to keep the "expand entries" approach as an
alternative, but I couldn't come up with a good heuristic for when
to use it instead.)
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-12-16 01:28:38 -08:00
|
|
|
#include <string>
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
/* #define DEBUG */
|
|
|
|
|
|
|
|
#include "parser.h"
|
2013-09-27 16:16:37 -07:00
|
|
|
#include "profile.h"
|
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
|
|
|
#include "mount.h"
|
2013-08-29 12:34:13 -07:00
|
|
|
#include "dbus.h"
|
2025-06-03 18:34:08 -03:00
|
|
|
#include "symtab.h"
|
parser: convert var expansion to use alternations
This patch converts the parser's variable expansion from adding new
entries for each additional variable value to incorporating an
alternation that includes all the values for the variable; e.g. given:
@{BINS}=/bin /usr/bin /sbin /usr/sbin
@{BINS}/binary ix,
rather than expanding to exntries for
/bin/binary
/usr/bin/binary
/sbin/binary
/usr/sbin/binary
one entry would remain that looks like:
{/bin,/usr/bin,/sbin,/usr/sbin}/binary
One complication with this patch is that we try to prevent mistakes for
our users with variable expansion around '/'s; it's common for people to
write profiles that contain things like:
@{BAR}=/bingo/*/ /bango/
/foo/@{BAR}/baz
We already have a post-processing step that walks entries looking
for multiple sequences of '/'s and filters them into single
'/' which worked when creating new entries for each variable
expansion. Converting to alternation expansion breaks this filtering,
so code is added that removes leading and trailing slashes in variable
values in the expansion if the character immediately preceding or
following the variable is also a slash.
The intent behind this is to reduce the amount of memory allocations
and structure walking that needed to occur in when converting from the
entry strings to the back end nodes. Examples with real world profiles
showed performance improvements ranging from 2.5% to 10%. However,
because the back end operations are sensitive to the front end inputs,
it is possible for worse results to occur; for example, it takes the
simple_tests/vars/vars_stress_0[123].sd tests significantly longer to
complete after this patch is applied (vars_stress_03.sd in particular
takes ~23 times longer). An initial analysis of profiling output in
this negative case looks like it causes the tree simplification in
the back end to do more work for unknown reasons.
On the other hand, the test simple_tests/vars/vars_dbus_9.sd
(introduced in "[patch 09/12] parser: more dbus variable testcases")
takes ~1 sec to complete on my laptop before this patch, and roughly
0.01s with this patch applied.
(One option would be to keep the "expand entries" approach as an
alternative, but I couldn't come up with a good heuristic for when
to use it instead.)
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-12-16 01:28:38 -08:00
|
|
|
|
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
|
|
|
/* doesn't handle variables in options atm */
|
2014-04-07 03:16:50 -07:00
|
|
|
int expand_entry_variables(char **name)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2025-06-03 18:34:08 -03:00
|
|
|
return variable::expand_by_alternation(name);
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int process_variables_in_entries(struct cod_entry *entry_list)
|
|
|
|
{
|
2013-09-27 16:16:37 -07:00
|
|
|
int error = 0;
|
2006-04-11 21:52:54 +00:00
|
|
|
struct cod_entry *entry;
|
|
|
|
|
2007-02-27 02:29:16 +00:00
|
|
|
list_for_each(entry_list, entry) {
|
2014-04-07 03:16:50 -07:00
|
|
|
error = expand_entry_variables(&entry->name);
|
2013-09-27 16:16:37 -07:00
|
|
|
if (error)
|
|
|
|
return error;
|
2015-06-06 01:28:12 -07:00
|
|
|
if (entry->link_name) {
|
|
|
|
error = expand_entry_variables(&entry->link_name);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
}
|
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
|
|
|
}
|
|
|
|
|
2013-09-27 16:16:37 -07:00
|
|
|
return 0;
|
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
|
|
|
}
|
|
|
|
|
2014-04-07 03:16:50 -07:00
|
|
|
static int process_variables_in_rules(Profile &prof)
|
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
|
|
|
{
|
2014-04-07 03:16:50 -07:00
|
|
|
for (RuleList::iterator i = prof.rule_ents.begin(); i != prof.rule_ents.end(); i++) {
|
2023-07-03 23:52:57 -07:00
|
|
|
if ((*i)->skip())
|
2021-09-19 00:59:45 -07:00
|
|
|
continue;
|
|
|
|
int error = (*i)->expand_variables();
|
2013-09-27 16:16:37 -07:00
|
|
|
if (error)
|
|
|
|
return error;
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2013-09-27 16:16:37 -07:00
|
|
|
return 0;
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2025-02-25 19:18:58 -03:00
|
|
|
|
|
|
|
static int process_variable_in_attach_disconnected(char **disconnected)
|
|
|
|
{
|
|
|
|
int error = expand_entry_variables(disconnected);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
filter_slashes(*disconnected);
|
|
|
|
// TODO: semantic check should go somewhere else
|
|
|
|
if ((*disconnected)[0] != '/')
|
|
|
|
yyerror(_("attach_disconnected path must begin with a /"));
|
|
|
|
int n = strlen(*disconnected);
|
|
|
|
// removing trailing / */
|
|
|
|
while (n && (*disconnected)[n-1] == '/')
|
|
|
|
(*disconnected)[--n] = 0;
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2015-07-10 18:11:17 -07:00
|
|
|
static int process_variables_in_name(Profile &prof)
|
|
|
|
{
|
|
|
|
/* this needs to be done before alias expansion, ie. altnames are
|
|
|
|
* setup
|
|
|
|
*/
|
|
|
|
int error = expand_entry_variables(&prof.name);
|
2025-04-20 16:34:51 -07:00
|
|
|
if (!error) {
|
|
|
|
if (prof.attachment)
|
|
|
|
error = expand_entry_variables(&prof.attachment);
|
|
|
|
else if (prof.name[0] == '/') {
|
|
|
|
/* had to wait to do this until after processing the
|
|
|
|
* variables in the profile name
|
|
|
|
*/
|
|
|
|
prof.attachment = strdup(local_name(prof.name));
|
|
|
|
if (!prof.attachment) {
|
|
|
|
errno = ENOMEM;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
filter_slashes(prof.attachment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-25 19:18:58 -03:00
|
|
|
if (!error && prof.flags.disconnected_path)
|
|
|
|
error = process_variable_in_attach_disconnected(&prof.flags.disconnected_path);
|
|
|
|
if (!error && prof.flags.disconnected_ipc)
|
|
|
|
error = process_variable_in_attach_disconnected(&prof.flags.disconnected_ipc);
|
2015-07-10 18:11:17 -07:00
|
|
|
return error;
|
|
|
|
}
|
2013-08-29 12:34:13 -07:00
|
|
|
|
2015-07-10 18:11:38 -07:00
|
|
|
static std::string escape_re(std::string str)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < str.length(); i++) {
|
|
|
|
if (str[i] == '\\') {
|
|
|
|
/* skip \ and follow char. Skipping \ and first
|
|
|
|
* char is enough for multichar escape sequence
|
|
|
|
*/
|
|
|
|
i++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strchr("{}[]*?", str[i]) != NULL) {
|
|
|
|
str.insert(i++, "\\");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2013-09-27 16:16:37 -07:00
|
|
|
int process_profile_variables(Profile *prof)
|
2006-04-11 21:52:54 +00:00
|
|
|
{
|
2025-06-03 18:34:08 -03:00
|
|
|
int error = 0;
|
|
|
|
variable *saved_exec_path = NULL;
|
|
|
|
variable *saved_attach_path = NULL;
|
2025-07-18 14:26:35 -03:00
|
|
|
variable *tmp = NULL;
|
2014-04-23 16:38:29 -07:00
|
|
|
|
2015-07-10 18:11:17 -07:00
|
|
|
/* needs to be before PROFILE_NAME_VARIABLE so that variable will
|
|
|
|
* have the correct name
|
|
|
|
*/
|
|
|
|
error = process_variables_in_name(*prof);
|
|
|
|
|
2025-04-20 16:34:51 -07:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* escape profile name elements that could be interpreted as
|
|
|
|
* regular expressions.
|
|
|
|
*/
|
2025-06-03 18:34:08 -03:00
|
|
|
error = symtab::add_var(PROFILE_NAME_VARIABLE, escape_re(prof->get_name(false)).c_str());
|
2025-04-20 16:34:51 -07:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (prof->attachment) {
|
|
|
|
/* IF we didn't want a path based profile name to generate
|
|
|
|
* an attachment. The code could be moved here. Add the
|
|
|
|
* output fed into the vars directly instead of setting
|
|
|
|
* the attachment.
|
2015-07-10 18:11:38 -07:00
|
|
|
*/
|
2025-04-20 16:34:51 -07:00
|
|
|
/* need to take into account alias, but not yet */
|
2025-06-03 18:34:08 -03:00
|
|
|
saved_attach_path = symtab::delete_var(PROFILE_ATTACH_VAR);
|
|
|
|
error = symtab::add_var(PROFILE_ATTACH_VAR, (const char*) prof->attachment);
|
2025-04-20 16:34:51 -07:00
|
|
|
if (error)
|
|
|
|
goto cleanup_name;
|
|
|
|
/* update to use kernel vars if available */
|
2025-06-03 18:34:08 -03:00
|
|
|
saved_exec_path = symtab::delete_var(PROFILE_EXEC_VAR);
|
|
|
|
error = symtab::add_var(PROFILE_EXEC_VAR, (const char*) prof->attachment);
|
2025-04-20 16:34:51 -07:00
|
|
|
if (error)
|
|
|
|
goto cleanup_attach;
|
2015-07-10 18:11:38 -07:00
|
|
|
}
|
2014-04-23 16:38:29 -07:00
|
|
|
|
2025-04-20 16:34:51 -07:00
|
|
|
error = process_variables_in_entries(prof->entries);
|
|
|
|
if (error)
|
|
|
|
goto cleanup;
|
|
|
|
error = process_variables_in_rules(*prof);
|
2013-08-29 12:34:13 -07:00
|
|
|
|
2025-04-20 16:34:51 -07:00
|
|
|
cleanup:
|
|
|
|
/* ideally these variables would be local scoped and we would not
|
|
|
|
* have to clean them up here, but unfortunately variables
|
|
|
|
* don't support that yet.
|
|
|
|
*/
|
|
|
|
if (prof->attachment) {
|
2025-07-18 14:26:35 -03:00
|
|
|
tmp = symtab::delete_var(PROFILE_EXEC_VAR);
|
|
|
|
delete tmp;
|
|
|
|
if (saved_exec_path) {
|
2025-06-03 18:34:08 -03:00
|
|
|
symtab::add_var(*saved_exec_path);
|
2025-07-18 14:26:35 -03:00
|
|
|
delete saved_exec_path;
|
|
|
|
}
|
2025-04-20 16:34:51 -07:00
|
|
|
}
|
|
|
|
cleanup_attach:
|
|
|
|
if (prof->attachment) {
|
2025-07-18 14:26:35 -03:00
|
|
|
tmp = symtab::delete_var(PROFILE_ATTACH_VAR);
|
|
|
|
delete tmp;
|
|
|
|
if (saved_attach_path) {
|
2025-06-03 18:34:08 -03:00
|
|
|
symtab::add_var(*saved_attach_path);
|
2025-07-18 14:26:35 -03:00
|
|
|
delete saved_attach_path;
|
|
|
|
}
|
2025-04-20 16:34:51 -07:00
|
|
|
}
|
|
|
|
cleanup_name:
|
2025-07-18 14:26:35 -03:00
|
|
|
tmp = symtab::delete_var(PROFILE_NAME_VARIABLE);
|
|
|
|
delete tmp;
|
2014-04-23 16:38:29 -07:00
|
|
|
|
2025-04-20 16:34:51 -07:00
|
|
|
out:
|
2006-04-11 21:52:54 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef UNIT_TEST
|
2013-09-27 16:16:37 -07:00
|
|
|
|
|
|
|
#include "unit_test.h"
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
int test_split_string(void)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
2025-06-03 18:34:08 -03:00
|
|
|
char *tst_string;
|
2013-10-01 10:59:04 -07:00
|
|
|
const char *prefix = "abcdefg";
|
|
|
|
const char *var = "boogie";
|
|
|
|
const char *suffix = "suffixication";
|
2025-06-03 18:34:08 -03:00
|
|
|
std::tuple<std::string, std::string, std::string> result;
|
|
|
|
std::string result_prefix;
|
|
|
|
std::string result_var;
|
|
|
|
std::string result_suffix;
|
|
|
|
char *pvar;
|
2006-04-11 21:52:54 +00:00
|
|
|
|
[v2: added clean-ups, backed off on some of the build silencing]
This is a rather large rearrangement of how a subset of the parser global
variables are defined. Right now, there are unit tests built without
linking against parser_main.c. As a result, none of the globals defined in
parser_main.c could be used in the code that is built for unit tests
(misc, regex, symtab, variable). To get a clean build, either stubs needed
to be added to "#ifdef UNIT_TEST" blocks in each .c file, or we had to
depend on link-time optimizations that would throw out the unused routines.
First, this is a problem because all the compile-time warnings had to be
explicitly silenced, so reviewing the build logs becomes difficult on
failures, and we can potentially (in really unlucky situations) test
something that isn't actually part of the "real" parser.
Second, not all compilers will allow this kind of linking (e.g. mips gcc),
and the missing symbols at link time will fail the entire build even though
they're technically not needed.
To solve all of this, I've moved all of the global variables used in lex,
yacc, and main to parser_common.c, and adjusted the .h files. On top of
this, I made sure to fully link the tst builds so all symbols are resolved
(including aare lib) and removedonly tst build-log silencing (for now,
deferring to another future patchset to consolidate the build silencing).
Signed-off-by: Kees Cook <kees.cook@canonical.com>
2011-05-13 02:12:49 -07:00
|
|
|
asprintf(&tst_string, "%s@{%s}%s", prefix, var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), prefix) == 0, "split string 1 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "split string 1 var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), suffix) == 0, "split string 1 suffix");
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
asprintf(&tst_string, "@{%s}%s", var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(result_prefix.empty(), "split string 2 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "split string 2 var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), suffix) == 0, "split string 2 suffix");
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
asprintf(&tst_string, "%s@{%s}", prefix, var);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), prefix) == 0, "split string 3 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "split string 3 var");
|
|
|
|
MY_TEST(result_suffix.empty(), "split string 3 suffix");
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
asprintf(&tst_string, "@{%s}", var);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(result_prefix.empty(), "split string 4 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "split string 4 var");
|
|
|
|
MY_TEST(result_suffix.empty(), "split string 4 suffix");
|
|
|
|
free(pvar);
|
|
|
|
free(tst_string);
|
|
|
|
|
|
|
|
asprintf(&tst_string, "%s%s%s", prefix, var, suffix);;
|
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
MY_TEST(result_prefix.empty(), "split string 5 prefix");
|
|
|
|
MY_TEST(result_var.empty(), "split string 5 var");
|
|
|
|
MY_TEST(result_suffix.empty(), "split string 5 suffix");
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int test_split_out_var(void)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
char *tst_string, *tmp;
|
2013-10-01 10:59:04 -07:00
|
|
|
const char *prefix = "abcdefg";
|
|
|
|
const char *var = "boogie";
|
|
|
|
const char *var2 = "V4rW1thNum5";
|
|
|
|
const char *var3 = "boogie_board";
|
|
|
|
const char *suffix = "suffixication";
|
2025-06-03 18:34:08 -03:00
|
|
|
std::tuple<std::string, std::string, std::string> result;
|
|
|
|
std::string result_prefix;
|
|
|
|
std::string result_var;
|
|
|
|
std::string result_suffix;
|
|
|
|
char *pvar = NULL;
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* simple case */
|
|
|
|
asprintf(&tst_string, "%s@{%s}%s", prefix, var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar != NULL, "extract_variable 1 pvar");
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), prefix) == 0, "extract_variable 1 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "extract_variable 1 var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), suffix) == 0, "extract_variable 1 suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* no prefix */
|
|
|
|
asprintf(&tst_string, "@{%s}%s", var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar != NULL, "extract_variable 2 pvar");
|
|
|
|
MY_TEST(result_prefix.empty(), "extract_variable 2 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "extract_variable 2 var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), suffix) == 0, "extract_variable 2 suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* no suffix */
|
|
|
|
asprintf(&tst_string, "%s@{%s}", prefix, var);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar != NULL, "extract_variable 3 pvar");
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), prefix) == 0, "extract_variable 3 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "extract_variable 3 var");
|
|
|
|
MY_TEST(result_suffix.empty(), "extract_variable 3 suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* var only */
|
|
|
|
asprintf(&tst_string, "@{%s}", var);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar != NULL, "extract_variable 4 pvar");
|
|
|
|
MY_TEST(result_prefix.empty(), "extract_variable 4 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "extract_variable 4 var");
|
|
|
|
MY_TEST(result_suffix.empty(), "extract_variable 4 suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* quoted var, shouldn't split */
|
|
|
|
asprintf(&tst_string, "%s\\@{%s}%s", prefix, var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
MY_TEST(result_prefix.empty(), "extract_variable - quoted @ prefix");
|
|
|
|
MY_TEST(result_var.empty(), "extract_variable - quoted @ var");
|
|
|
|
MY_TEST(result_suffix.empty(), "extract_variable - quoted @ suffix");
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* quoted \, split should succeed */
|
|
|
|
asprintf(&tst_string, "%s\\\\@{%s}%s", prefix, var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
2016-01-25 12:05:50 -08:00
|
|
|
tmp = strndup(tst_string, strlen(prefix) + 2);
|
2025-06-03 18:34:08 -03:00
|
|
|
MY_TEST(pvar != NULL, "extract_variable 5 pvar");
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), tmp) == 0, "extract_variable 5 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "extract_variable 5 var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), suffix) == 0, "extract_variable 5 suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
|
|
|
free(tmp);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* un terminated var, should fail */
|
|
|
|
asprintf(&tst_string, "%s@{%s%s", prefix, var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
MY_TEST(result_prefix.empty(), "extract_variable - un-terminated var prefix");
|
|
|
|
MY_TEST(result_var.empty(), "extract_variable - un-terminated var var");
|
|
|
|
MY_TEST(result_suffix.empty(), "extract_variable - un-terminated var suffix");
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* invalid char in var, should fail */
|
|
|
|
asprintf(&tst_string, "%s@{%s^%s}%s", prefix, var, var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar == NULL, "process_var - invalid char in var");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* two vars, should only strip out first */
|
|
|
|
asprintf(&tmp, "@{%s}%s}", suffix, suffix);
|
|
|
|
asprintf(&tst_string, "%s@{%s}%s", prefix, var, tmp);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar != NULL, "extract_variable 6 pvar");
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), prefix) == 0, "extract_variable 6 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "extract_variable 6 var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), tmp) == 0, "extract_variable 6 suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
|
|
|
free(tmp);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
/* quoted @ followed by var, split should succeed */
|
|
|
|
asprintf(&tst_string, "%s\\@@{%s}%s", prefix, var, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
2016-01-25 12:05:50 -08:00
|
|
|
tmp = strndup(tst_string, strlen(prefix) + 2);
|
2025-06-03 18:34:08 -03:00
|
|
|
MY_TEST(pvar != NULL, "extract_variable 7 pvar");
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), tmp) == 0, "extract_variable 7 prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var) == 0, "extract_variable 7 var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), suffix) == 0, "extract_variable 7 suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
|
|
|
free(tmp);
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2011-03-28 10:52:02 -07:00
|
|
|
/* numeric char in var, should succeed */
|
|
|
|
asprintf(&tst_string, "%s@{%s}%s", prefix, var2, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar != NULL, "extract_variable numeric var pvar");
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), prefix) == 0, "split out numeric var prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var2) == 0, "split numeric var var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), suffix) == 0, "split out numeric var suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2011-03-28 10:52:02 -07:00
|
|
|
|
|
|
|
/* numeric first char in var, should fail */
|
|
|
|
asprintf(&tst_string, "%s@{6%s}%s", prefix, var2, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar == NULL, "process_var - invalid char in var");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2011-03-28 10:52:02 -07:00
|
|
|
|
|
|
|
/* underscore char in var, should succeed */
|
|
|
|
asprintf(&tst_string, "%s@{%s}%s", prefix, var3, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar != NULL, "extract_variable underscore var pvar");
|
|
|
|
MY_TEST(strcmp(result_prefix.c_str(), prefix) == 0, "split out underscore var prefix");
|
|
|
|
MY_TEST(strcmp(pvar, var3) == 0, "split out underscore var");
|
|
|
|
MY_TEST(strcmp(result_suffix.c_str(), suffix) == 0, "split out underscore var suffix");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2011-03-28 10:52:02 -07:00
|
|
|
|
|
|
|
/* underscore first char in var, should fail */
|
|
|
|
asprintf(&tst_string, "%s@{_%s%s}%s", prefix, var2, var3, suffix);
|
2025-06-03 18:34:08 -03:00
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar == NULL, "process_var - invalid char in var");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
2016-01-25 12:05:50 -08:00
|
|
|
free(tst_string);
|
2011-03-28 10:52:02 -07:00
|
|
|
|
2025-06-03 18:34:08 -03:00
|
|
|
/* empty var name, should fail */
|
|
|
|
asprintf(&tst_string, "%s@{}%s", prefix, suffix);
|
|
|
|
result = extract_variable(tst_string);
|
|
|
|
result_prefix = std::get<0>(result);
|
|
|
|
result_var = std::get<1>(result);
|
|
|
|
result_suffix = std::get<2>(result);
|
|
|
|
pvar = variable::process_var(result_var.c_str());
|
|
|
|
MY_TEST(pvar == NULL, "process_var - empty var name");
|
|
|
|
if (pvar)
|
|
|
|
free(pvar);
|
|
|
|
free(tst_string);
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
retval = test_split_string();
|
|
|
|
if (retval != 0)
|
|
|
|
rc = retval;
|
|
|
|
|
|
|
|
retval = test_split_out_var();
|
|
|
|
if (retval != 0)
|
|
|
|
rc = retval;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
#endif /* UNIT_TEST */
|