Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix regex segfault in history parsing #1441

Merged
merged 2 commits into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion libmamba/include/mamba/core/output.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ namespace mamba
none = 0,
red = 1 << 1,
green = 1 << 2,
yellow = 1 << 3
yellow = 1 << 3,
bold_blue = 1 << 4
};

struct FormattedString
Expand Down
11 changes: 9 additions & 2 deletions libmamba/src/api/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,12 @@ namespace mamba
return;
}

std::cout << "List of packages in environment: " << ctx.target_prefix << std::endl;
std::cout << "List of packages in environment: " << ctx.target_prefix << "\n\n";

formatted_pkg formatted_pkgs;

std::vector<formatted_pkg> packages;
auto requested_specs = prefix_data.history().get_requested_specs_map();

// order list of packages from prefix_data by alphabetical order
for (const auto& package : prefix_data.m_package_records)
Expand Down Expand Up @@ -124,7 +125,13 @@ namespace mamba

for (auto p : packages)
{
t.add_row({ p.name, p.version, p.build, p.channel });
printers::FormattedString formatted_name(p.name);
if (requested_specs.find(p.name) != requested_specs.end())
{
formatted_name = printers::FormattedString(p.name);
formatted_name.flag = printers::format::bold_blue;
}
t.add_row({ formatted_name, p.version, p.build, p.channel });
}

t.print(std::cout);
Expand Down
54 changes: 24 additions & 30 deletions libmamba/src/core/history.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ namespace mamba
std::string line;
while (getline(in_file, line))
{
// line.strip()
if (line.size() == 0)
continue;
std::smatch base_match;
if (std::regex_match(line, base_match, head_re))
{
ParseResult p;
p.head_line = base_match[1].str();
res.push_back(std::move(p));
res.push_back(p);
}
else if (line[0] == '#')
{
Expand Down Expand Up @@ -75,70 +74,65 @@ namespace mamba

bool History::parse_comment_line(const std::string& line, UserRequest& req)
{
static std::regex com_pat("#\\s*cmd:\\s*(.+)");
static std::regex conda_v_pat("#\\s*conda version:\\s*(.+)");
static std::regex spec_pat("#\\s*(\\w+)\\s*specs:\\s*(.+)?");
std::size_t colon_idx = line.find_first_of(':');
if (colon_idx == std::string::npos) return false;

std::smatch rmatch;
std::string key(strip(line.substr(1, colon_idx - 1)));
std::string value(strip(line.substr(colon_idx + 1)));

if (std::regex_match(line, rmatch, com_pat))
if (key == "conda version")
{
req.cmd = rmatch[1].str();
req.conda_version = value;
}
else if (std::regex_match(line, rmatch, conda_v_pat))
else if (key == "cmd")
{
req.conda_version = rmatch[1].str();
req.cmd = value;
}
else if (std::regex_match(line, rmatch, spec_pat))
else if (ends_with(key, " specs"))
{
std::string action = rmatch[1].str();
std::string elems = rmatch[2].str();

std::cmatch ematch;
std::vector<std::string> pkg_specs;

std::string action = key.substr(0, key.find_first_of(" "));
// small parser for pythonic lists
std::size_t idx_start = elems.find_first_of("\'\"");
std::vector<std::string> pkg_specs;
std::size_t idx_start = value.find_first_of("\'\"");
std::size_t idx_end, idx_search;
idx_search = idx_start + 1;
std::string needle = "X";

while (true)
{
needle[0] = elems[idx_start];
idx_end = elems.find_first_of(needle.c_str(), idx_search);
if (idx_end != std::string::npos && elems[idx_end - 1] != '\\')
needle[0] = value[idx_start];
idx_end = value.find_first_of(needle.c_str(), idx_search);
if (idx_end != std::string::npos && value[idx_end - 1] != '\\')
{
pkg_specs.push_back(elems.substr(idx_start + 1, idx_end - 1 - idx_start));
idx_start = elems.find_first_of("\'\"", idx_end + 1);
pkg_specs.push_back(value.substr(idx_start + 1, idx_end - 1 - idx_start));
idx_start = value.find_first_of("\'\"", idx_end + 1);
idx_search = idx_start + 1;
}
else
{
idx_search = idx_end;
}
if (idx_start >= elems.size() || idx_start == std::string::npos)
if (idx_start >= value.size() || idx_start == std::string::npos)
{
break;
}
if (idx_search >= elems.size() || idx_search == std::string::npos)
if (idx_search >= value.size() || idx_search == std::string::npos)
{
throw std::runtime_error("Parsing of history file failed");
}
// pkg_specs.push_back(ematch[1].str());
// text_iter += ematch.position() + ematch.length();
}

if (action == "update" || action == "install" || action == "create")
{
req.update = std::move(pkg_specs);
req.update = pkg_specs;
}
else if (action == "remove" || action == "uninstall")
{
req.remove = std::move(pkg_specs);
req.remove = pkg_specs;
}
else if (action == "neutered")
{
req.neutered = std::move(pkg_specs);
req.neutered = pkg_specs;
}
}
return true;
Expand Down
3 changes: 3 additions & 0 deletions libmamba/src/core/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ namespace mamba
if (static_cast<std::size_t>(row[j].flag)
& static_cast<std::size_t>(format::yellow))
out << termcolor::yellow;
if (static_cast<std::size_t>(row[j].flag)
& static_cast<std::size_t>(format::bold_blue))
out << termcolor::blue << termcolor::bold;
}
if (this->m_align[j] == alignment::left)
{
Expand Down