2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 10:07:12 +00:00
apparmor/parser/symtab.cc

173 lines
3.9 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2025
* Canonical Ltd. (All rights reserved)
*
* 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 Canonical Ltd.
*/
#include "symtab.h"
template <typename T>
int symtab::add_var(const char *var, T value)
{
char *var_name = variable::process_var(var);
if (!var_name)
return 1;
const auto search = my_symtab.find(var_name);
if (search != my_symtab.end()) {
/* already existing variable */
PERROR("'%s' is already defined\n", var);
free(var_name);
return 1;
}
my_symtab.emplace(var_name, variable(var_name, value));
free(var_name);
return 0;
}
int symtab::add_var(const char *var, int value)
{
return add_var<int>(var, value);
}
int symtab::add_var(const char *var, struct value_list *value)
{
return add_var<struct value_list *>(var, value);
}
int symtab::add_var(const char *var_name, const char *value)
{
/* note that here var_name must be processed already */
const auto search = my_symtab.find(var_name);
if (search != my_symtab.end()) {
/* already existing variable */
PERROR("'%s' is already defined\n", var_name);
return 1;
}
my_symtab.emplace(var_name, variable(var_name, value));
return 0;
}
int symtab::add_var(variable var)
{
const auto search = my_symtab.find(var.var_name);
if (search != my_symtab.end()) {
/* already existing variable */
PERROR("'%s' is already defined\n", var.var_name.c_str());
return 1;
}
my_symtab.emplace(var.var_name, var);
return 0;
}
variable *symtab::lookup_existing_symbol(const char *var_name)
{
if (!var_name)
return nullptr;
const auto var = my_symtab.find(var_name);
if (var == my_symtab.end()) {
return nullptr;
}
return &(var->second);
}
int symtab::add_set_value(const char *var_name, struct value_list *value)
{
char *pvar_name = variable::process_var(var_name);
variable *var = lookup_existing_symbol(pvar_name);
if (!var) {
PERROR("Failed to find declaration for: %s\n", pvar_name);
free(pvar_name);
return 1;
}
free(pvar_name);
return var->add_set_value(value);
}
variable *symtab::delete_var(const char *var_name)
{
variable *var = lookup_existing_symbol(var_name);
if (!var) {
return var;
}
if (var->type != sd_set) {
PERROR("ASSERT: delete_set_var: deleting %s but is a boolean variable\n",
var_name);
exit(1);
}
variable *save = new variable(*var);
my_symtab.erase(var->var_name);
return save;
}
void symtab::free_symtab()
{
my_symtab.erase(my_symtab.begin(), my_symtab.end());
}
void symtab::dump(bool do_expanded)
{
for (auto var : my_symtab) {
var.second.dump(do_expanded);
}
}
void symtab::expand_variables()
{
for (auto var : my_symtab) {
if (var.second.type != sd_boolean)
var.second.expand_variable();
}
}
variable *symtab::get_set_var(const char *name)
{
char *var_name = variable::process_var(name);
variable *var = lookup_existing_symbol(var_name);
if (!var) {
goto out;
}
if (var->type != sd_set) {
PERROR("Variable %s is not a set variable\n", var_name);
var = nullptr;
goto out;
}
var->expand_variable();
out:
free(var_name);
return var;
}
variable *symtab::get_boolean_var(const char *name)
{
char *var_name = variable::process_var(name);
variable *var = lookup_existing_symbol(var_name);
if (!var) {
goto out;
}
if (var->type != sd_boolean) {
PERROR("Variable %s is not a boolean variable\n", var_name);
var = nullptr;
goto out;
}
out:
free(var_name);
return var;
}
std::unordered_map<std::string, variable> symtab::my_symtab;