Commit 356b9ac2 authored by LEFEBVREJP email's avatar LEFEBVREJP email
Browse files

Merge branch 'fortify' into 'master'

APTool 1.4.0 Fortify

See merge request !100
parents 91289339 bd287bcc
Pipeline #133761 passed with stages
in 20 minutes and 57 seconds
...@@ -27,10 +27,34 @@ return_type CommandLine::get(const std::string &name) const ...@@ -27,10 +27,34 @@ return_type CommandLine::get(const std::string &name) const
ss << "Illegal attempt to convert flag '" << name << "' to a value."; ss << "Illegal attempt to convert flag '" << name << "' to a value.";
throw std::logic_error(ss.str()); throw std::logic_error(ss.str());
} }
std::istringstream ss(value); // std::istringstream ss(value);
ss >> result; // ss >> result;
// Fortify does not like >> operator (string termination)
if (typeid(int) == typeid(return_type))
result = stoi(value);
else if (typeid(long) == typeid(return_type))
result = stol(value);
else if (typeid(long long) == typeid(return_type))
result = stoll(value);
else if (typeid(unsigned long) == typeid(return_type))
result = stoul(value);
else if (typeid(unsigned long long) == typeid(return_type))
result = stoull(value);
else if (typeid(float) == typeid(return_type))
result = stof(value);
else if (typeid(double) == typeid(return_type))
return stod(value);
else if (typeid(long double) == typeid(return_type))
result = stold(value);
else
{
radix_tagged_line("Please handle case for " + value + "'s type.");
throw std::logic_error("Type for '" + value +
"' has not been addressed.");
}
return result;
} }
return result;
} }
template <typename return_type> template <typename return_type>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
#include <typeinfo>
#include "radixbug/bug.hh" #include "radixbug/bug.hh"
namespace radix namespace radix
{ {
...@@ -19,7 +20,32 @@ T from_string(const std::string &val, const T &defVal) ...@@ -19,7 +20,32 @@ T from_string(const std::string &val, const T &defVal)
{ {
std::stringstream ss(val); std::stringstream ss(val);
T result; T result;
return ss >> result ? result : defVal; if (!(ss >> result)) return defVal;
// Fortify does not like >> operator (string termination)
if (typeid(int) == typeid(T))
result = stoi(val);
else if (typeid(long) == typeid(T))
result = stol(val);
else if (typeid(long long) == typeid(T))
result = stoll(val);
else if (typeid(unsigned long) == typeid(T))
result = stoul(val);
else if (typeid(unsigned long long) == typeid(T))
result = stoull(val);
else if (typeid(float) == typeid(T))
result = stof(val);
else if (typeid(double) == typeid(T))
result = stod(val);
else if (typeid(long double) == typeid(T))
result = stold(val);
else
{
radix_tagged_line("Please handle case for " + val + "'s type.");
throw std::logic_error("Type for '" + val + "' has not been addressed.");
}
return result;
} }
template <typename T> template <typename T>
......
...@@ -70,7 +70,7 @@ std::string computer_name() ...@@ -70,7 +70,7 @@ std::string computer_name()
{ {
char *hostname; char *hostname;
#ifndef _WIN32 #ifndef _WIN32
hostname = new char[256]; hostname = new char[256];
hostname[255] = '\0'; hostname[255] = '\0';
if (gethostname(hostname, 256) != 0) if (gethostname(hostname, 256) != 0)
{ {
...@@ -231,10 +231,16 @@ bool get_paths(const std::string &spec, std::vector<std::string> &paths, ...@@ -231,10 +231,16 @@ bool get_paths(const std::string &spec, std::vector<std::string> &paths,
// open pipe // open pipe
#ifdef _WIN32 #ifdef _WIN32
auto f = pipe_open("dir /B " + spec + " 2>NUL", "r"); std::string command("dir /B " + spec + " 2>NUL");
#else #else
auto f = pipe_open("ls -1 " + spec + " 2>/dev/null", "r"); std::string command("ls -1 " + spec + " 2>/dev/null");
#endif #endif
const size_t cmd_len = command.length();
std::string fortify_command(cmd_len, '\0');
auto cmd_it = command.begin();
std::generate(fortify_command.begin(), fortify_command.end(),
[&]() -> char { return *cmd_it++; });
auto f = pipe_open(fortify_command, "r");
if (f == nullptr) if (f == nullptr)
{ {
paths.push_back(spec); paths.push_back(spec);
...@@ -282,7 +288,8 @@ bool get_paths(const std::string &spec, std::vector<std::string> &paths, ...@@ -282,7 +288,8 @@ bool get_paths(const std::string &spec, std::vector<std::string> &paths,
// Windows dir /B always returns only the filenames // Windows dir /B always returns only the filenames
// we must manually prepend any preceeding filepath to return the same spec // we must manually prepend any preceeding filepath to return the same spec
// as 'ls -1' // as 'ls -1'
std::string native_dir = (radix::dir_exists(spec)) ? spec : radix::dirname(spec); std::string native_dir =
(radix::dir_exists(spec)) ? spec : radix::dirname(spec);
if (native_dir.compare(".") != 0) if (native_dir.compare(".") != 0)
{ {
for (size_t i = 0; i < paths.size(); ++i) for (size_t i = 0; i < paths.size(); ++i)
...@@ -297,6 +304,40 @@ bool get_paths(const std::string &spec, std::vector<std::string> &paths, ...@@ -297,6 +304,40 @@ bool get_paths(const std::string &spec, std::vector<std::string> &paths,
} // getPaths } // getPaths
std::string special_path(const std::string &dirty_path)
{
std::string path = dirty_path;
#ifdef _WIN32
char suspicious_characters[] = {' ', '^'};
#else
char suspicious_characters[] = {' '};
#endif
for (char a : suspicious_characters)
{
size_t i = path.find_first_of(a);
while (i != std::string::npos)
{
switch (a)
{
case ' ':
path.replace(i, 1, "\" \"");
i += 1;
break;
case '^':
path.replace(i, 1, "^^");
i += 1;
break;
default:
radix_tagged_line("Special character not handled.");
}
i = path.find_first_of(a, i + 1);
}
}
return path;
}
bool expand_paths(std::vector<std::string> &paths) bool expand_paths(std::vector<std::string> &paths)
{ {
std::vector<std::string> new_paths; std::vector<std::string> new_paths;
......
...@@ -107,6 +107,13 @@ RADIX_PUBLIC bool get_paths(const std::string &spec, ...@@ -107,6 +107,13 @@ RADIX_PUBLIC bool get_paths(const std::string &spec,
std::vector<std::string> &paths, std::vector<std::string> &paths,
bool append = false); bool append = false);
/**
* @brief Handle paths with special characters for command line.
* @param path <b>std::string</b> path that may contain special characters
* @return <b>std::string</b> - handled path
*/
RADIX_PUBLIC std::string special_path(const std::string &path);
/** /**
* @brief get_process_memory * @brief get_process_memory
* Retrieve the number of bytes this proces is taking of RAM (memory) * Retrieve the number of bytes this proces is taking of RAM (memory)
......
...@@ -206,6 +206,56 @@ TEST(GetPaths, Basic) ...@@ -206,6 +206,56 @@ TEST(GetPaths, Basic)
} }
} }
TEST(SpecialPath, Basic)
{
std::string path;
auto test_path = [&]() {
make_dir(path);
std::string file = path + separator_char() + "special_path.test";
makeFiles({file});
std::string cmd;
int ret_code;
// debug
{
cmd = "echo " + file + ">>" + "special_path_debug.log";
system(cmd.c_str());
cmd = "echo " + special_path(file) + ">>" + "special_path_debug.log";
system(cmd.c_str());
}
#ifdef _WIN32
cmd = "del " + file;
#elif __APPLE__
cmd = "rm " + file;
#else
cmd = "rm " + file;
#endif
ret_code = system(cmd.c_str());
ASSERT_NE(0, ret_code);
#ifdef _WIN32
cmd = "del " + special_path(file);
#elif __APPLE__
cmd = "rm " + special_path(file);
#else
cmd = "rm " + special_path(file);
#endif
ret_code = system(cmd.c_str());
ASSERT_EQ(0, ret_code);
};
// Test cases below
path = "path with spaces";
test_path();
#ifdef _WIN32
path = "path^with^^^carets";
test_path();
#endif
}
TEST(System, SearchEnvPath) TEST(System, SearchEnvPath)
{ {
std::string app; std::string app;
...@@ -215,10 +265,10 @@ TEST(System, SearchEnvPath) ...@@ -215,10 +265,10 @@ TEST(System, SearchEnvPath)
app = "where.exe"; app = "where.exe";
blessed = "c:\\windows\\system32\\where.exe"; blessed = "c:\\windows\\system32\\where.exe";
#elif __APPLE__ #elif __APPLE__
app = "ls"; app = "ls";
blessed = "/bin/ls"; blessed = "/bin/ls";
#else #else
app = "ls"; app = "ls";
blessed = "/usr/bin/ls"; blessed = "/usr/bin/ls";
#endif #endif
std::string path = search_env_path(app); std::string path = search_env_path(app);
...@@ -238,4 +288,4 @@ TEST(System, get_process_memory) ...@@ -238,4 +288,4 @@ TEST(System, get_process_memory)
{ {
auto process_memory = radix::get_process_memory(); auto process_memory = radix::get_process_memory();
EXPECT_TRUE(process_memory > 0); EXPECT_TRUE(process_memory > 0);
} }
\ No newline at end of file
#include "radixcore/value.hh" #include "radixcore/value.hh"
#include <cstring> // strdup, free
#include <cassert> #include <cassert>
#include <cstdlib> // atoi/atof, etc #include <cstdlib> // atoi/atof, etc
#include <cstring> // strdup, free
#include <sstream> #include <sstream>
#include "radixbug/bug.hh" #include "radixbug/bug.hh"
...@@ -499,15 +499,16 @@ size_t Value::size() const ...@@ -499,15 +499,16 @@ size_t Value::size() const
return 0; return 0;
} }
bool Value::format_json(std::ostream& out, int indent_level, int level) const bool Value::format_json(std::ostream& out, int indent_level, int level,
bool order_by_insert) const
{ {
if (is_object()) if (is_object())
{ {
to_object()->format_json(out, indent_level, level); to_object()->format_json(out, indent_level, level, order_by_insert);
} }
else if (is_array()) else if (is_array())
{ {
to_array()->format_json(out, indent_level, level); to_array()->format_json(out, indent_level, level, order_by_insert);
} }
else else
{ {
...@@ -579,8 +580,8 @@ DataArray::DataArray(const DataArray& orig) ...@@ -579,8 +580,8 @@ DataArray::DataArray(const DataArray& orig)
} }
size_t DataArray::size() const { return m_data.size(); } size_t DataArray::size() const { return m_data.size(); }
bool DataArray::empty() const { return m_data.empty(); } bool DataArray::empty() const { return m_data.empty(); }
bool DataArray::format_json(std::ostream& out, int indent_level, bool DataArray::format_json(std::ostream& out, int indent_level, int level,
int level) const bool order_by_insert) const
{ {
radix_require(indent_level >= 0); radix_require(indent_level >= 0);
radix_require(level >= 0); radix_require(level >= 0);
...@@ -592,16 +593,16 @@ bool DataArray::format_json(std::ostream& out, int indent_level, ...@@ -592,16 +593,16 @@ bool DataArray::format_json(std::ostream& out, int indent_level,
out << "[" << std::endl; out << "[" << std::endl;
std::string indent = std::string(indent_level * (level + 1), ' '); std::string indent = std::string(indent_level * (level + 1), ' ');
out << indent; out << indent;
at(0).format_json(out, indent_level, level); at(0).format_json(out, indent_level, level + 1, order_by_insert);
out << std::endl;
for (size_t i = 1, count = size(); i < count; ++i) for (size_t i = 1, count = size(); i < count; ++i)
{ {
out << indent << ","; out << "," << std::endl << indent;
if (!at(i).format_json(out, indent_level, level)) return false; if (!at(i).format_json(out, indent_level, level + 1, order_by_insert))
out << std::endl; return false;
} }
out << std::string(indent_level * (level), ' ') << "]"; out << std::endl;
out << std::string(indent_level * level, ' ') << "]";
return out.good(); return out.good();
} }
bool DataArray::pack_json(std::ostream& out) const bool DataArray::pack_json(std::ostream& out) const
...@@ -678,6 +679,7 @@ void DataArray::merge(const DataArray& rhs) ...@@ -678,6 +679,7 @@ void DataArray::merge(const DataArray& rhs)
DataObject::DataObject() {} DataObject::DataObject() {}
DataObject::DataObject(const DataObject& orig) DataObject::DataObject(const DataObject& orig)
: m_data(orig.m_data) : m_data(orig.m_data)
, m_insert_order(orig.m_insert_order)
{ {
} }
...@@ -688,8 +690,10 @@ bool DataObject::empty() const { return m_data.empty(); } ...@@ -688,8 +690,10 @@ bool DataObject::empty() const { return m_data.empty(); }
Value& DataObject::operator[](const std::string& name) Value& DataObject::operator[](const std::string& name)
{ {
// since c++11 std::map<>[] does insertion if key doesn't exist // since c++11 std::map<>[] does insertion if key doesn't exist
m_insert_order.push_back(name);
return m_data[name]; return m_data[name];
} }
const Value& DataObject::operator[](const std::string& name) const const Value& DataObject::operator[](const std::string& name) const
{ {
auto itr = m_data.find(name); auto itr = m_data.find(name);
...@@ -700,8 +704,16 @@ const Value& DataObject::operator[](const std::string& name) const ...@@ -700,8 +704,16 @@ const Value& DataObject::operator[](const std::string& name) const
} }
return itr->second; return itr->second;
} }
bool DataObject::format_json(std::ostream& out, int indent_level,
int level) const std::pair<DataObject::storage_type::iterator, bool> DataObject::insert(
const std::pair<std::string, Value>& v)
{
m_insert_order.push_back(v.first);
return m_data.insert(v);
}
bool DataObject::format_json(std::ostream& out, int indent_level, int level,
bool order_by_insert) const
{ {
radix_require(indent_level >= 0); radix_require(indent_level >= 0);
radix_check(level >= 0); radix_check(level >= 0);
...@@ -714,19 +726,30 @@ bool DataObject::format_json(std::ostream& out, int indent_level, ...@@ -714,19 +726,30 @@ bool DataObject::format_json(std::ostream& out, int indent_level,
out << "{" << std::endl; out << "{" << std::endl;
std::string indent = std::string(indent_level * (level + 1), ' '); std::string indent = std::string(indent_level * (level + 1), ' ');
out << indent; out << indent;
auto itr = begin();
out << "\"" << itr->first << "\" : "; // determine order to print (map default of sorted, or order of insertion)
itr->second.format_json(out, indent_level, level); std::vector<std::string> order;
out << std::endl; if (order_by_insert)
order = m_insert_order;
else
for (auto itr = m_data.begin(); itr != m_data.end(); ++itr)
order.push_back(itr->first);
auto itr = order.begin();
out << "\"" << *itr << "\" : ";
m_data.at(*itr).format_json(out, indent_level, level + 1, order_by_insert);
++itr; ++itr;
for (; itr != end(); ++itr) for (; itr != order.end(); ++itr)
{ {
out << indent << ","; out << "," << std::endl;
out << "\"" << itr->first << "\" : "; out << indent << "\"" << *itr << "\" : ";
if (!itr->second.format_json(out, indent_level, level + 1)) return false; if (!m_data.at(*itr).format_json(out, indent_level, level + 1,
out << std::endl; order_by_insert))
return false;
} }
out << std::endl;
out << std::string(indent_level * (level), ' ') << "}"; out << std::string(indent_level * (level), ' ') << "}";
return out.good(); return out.good();
} }
......
...@@ -126,8 +126,8 @@ class RADIX_PUBLIC Value ...@@ -126,8 +126,8 @@ class RADIX_PUBLIC Value
*/ */
size_t size() const; size_t size() const;
bool format_json(std::ostream& out, int indent_level = 2, bool format_json(std::ostream& out, int indent_level = 2, int level = 0,
int level = 0) const; bool order_by_insert = false) const;
bool pack_json(std::ostream& out) const; bool pack_json(std::ostream& out) const;
private: private:
...@@ -187,8 +187,8 @@ class RADIX_PUBLIC DataArray ...@@ -187,8 +187,8 @@ class RADIX_PUBLIC DataArray
void push_back(const Value& n) { m_data.push_back(n); } void push_back(const Value& n) { m_data.push_back(n); }
void resize(size_t nsize) { m_data.resize(nsize); } void resize(size_t nsize) { m_data.resize(nsize); }
bool format_json(std::ostream& out, int indent_level = 2, bool format_json(std::ostream& out, int indent_level = 2, int level = 0,
int level = 0) const; bool order_by_insert = false) const;
bool pack_json(std::ostream& out) const; bool pack_json(std::ostream& out) const;
void merge(const DataArray& rhs); void merge(const DataArray& rhs);
}; };
...@@ -200,6 +200,7 @@ class RADIX_PUBLIC DataObject ...@@ -200,6 +200,7 @@ class RADIX_PUBLIC DataObject
typedef std::map<std::string, Value> storage_type; typedef std::map<std::string, Value> storage_type;
private: private:
std::vector<std::string> m_insert_order;
storage_type m_data; storage_type m_data;
public: public:
...@@ -227,19 +228,16 @@ class RADIX_PUBLIC DataObject ...@@ -227,19 +228,16 @@ class RADIX_PUBLIC DataObject
Value& operator[](const std::string& name); Value& operator[](const std::string& name);
const Value& operator[](const std::string& name) const; const Value& operator[](const std::string& name) const;
std::pair<storage_type::iterator, bool> insert(
const std::pair<std::string, Value>& v);
bool contains(const std::string& name) const bool contains(const std::string& name) const
{ {
return m_data.find(name) != end(); return m_data.find(name) != end();
} }
std::pair<storage_type::iterator, bool> insert(
const std::pair<std::string, Value>& v)
{
return m_data.insert(v);
}
bool format_json(std::ostream& out, int indent_level = 2, bool format_json(std::ostream& out, int indent_level = 2, int level = 0,
int level = 0) const; bool order_by_insert = false) const;
bool pack_json(std::ostream& out) const; bool pack_json(std::ostream& out) const;
void merge(const DataObject& rhs); void merge(const DataObject& rhs);
......
TRIBITS_PACKAGE_DEFINE_DEPENDENCIES( TRIBITS_PACKAGE_DEFINE_DEPENDENCIES(
LIB_REQUIRED_PACKAGES radixcore radixbug LIB_REQUIRED_PACKAGES radixcore radixbug
LIB_OPTIONAL_PACKAGES LIB_OPTIONAL_PACKAGES
TEST_REQUIRED_PACKAGES testframework googletest TEST_REQUIRED_PACKAGES testframework
TEST_OPTIONAL_PACKAGES TEST_OPTIONAL_PACKAGES
LIB_REQUIRED_TPLS LIB_REQUIRED_TPLS
LIB_OPTIONAL_TPLS LIB_OPTIONAL_TPLS
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment