From d37076a33296877fee3154db689f2990785aed94 Mon Sep 17 00:00:00 2001
From: Bent Bisballe Nyeng <deva@aasimon.org>
Date: Sat, 14 Jan 2023 18:14:03 +0100
Subject: Escape all user-input strings when writing configuration.cc

---
 src/configure.cc | 29 +++++++++++++++--------------
 src/util.cc      | 17 +++++++++++++++++
 src/util.h       |  2 ++
 3 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/src/configure.cc b/src/configure.cc
index 8e88092..3bb2d48 100644
--- a/src/configure.cc
+++ b/src/configure.cc
@@ -16,6 +16,7 @@
 #include "rebuild.h"
 #include "externals.h"
 #include "tools.h"
+#include "util.h"
 
 std::filesystem::path configurationFile("configuration.cc");
 std::filesystem::path configHeaderFile("config.h");
@@ -495,38 +496,38 @@ int regenerateCache(ctor::settings& settings,
 		istr << "		.args = {";
 		for(const auto& arg : args)
 		{
-			istr << "\"" << arg << "\",";
+			istr << "\"" << esc(arg) << "\",";
 		}
 		istr << "},\n";
 		istr << "		.env = {";
 		for(const auto& e : env)
 		{
-			istr << "{\"" << e.first << "\", \"" << e.second << "\"}, ";
+			istr << "{\"" << esc(e.first) << "\", \"" << esc(e.second) << "\"}, ";
 		}
 		istr << "},\n";
 
 		istr << "		.tools = {\n";
 		if(!builddir.empty())
 		{
-			istr << "			{ \"" << ctor::cfg::builddir << "\", \"" << builddir << "\" },\n";
+			istr << "			{ \"" << ctor::cfg::builddir << "\", \"" << esc(builddir) << "\" },\n";
 			ctor::builddir = builddir;
 		}
-		istr << "			{ \"" << ctor::cfg::host_cc << "\", \"" << host_cc << "\" },\n";
-		istr << "			{ \"" << ctor::cfg::host_cxx << "\", \"" << host_cxx << "\" },\n";
-		istr << "			{ \"" << ctor::cfg::host_ar << "\", \"" << host_ar << "\" },\n";
-		istr << "			{ \"" << ctor::cfg::host_ld << "\", \"" << host_ld << "\" },\n";
-		istr << "			{ \"" << ctor::cfg::build_cc << "\", \"" << build_cc << "\" },\n";
-		istr << "			{ \"" << ctor::cfg::build_cxx << "\", \"" << build_cxx << "\" },\n";
-		istr << "			{ \"" << ctor::cfg::build_ar << "\", \"" << build_ar << "\" },\n";
-		istr << "			{ \"" << ctor::cfg::build_ld << "\", \"" << build_ld << "\" },\n";
+		istr << "			{ \"" << ctor::cfg::host_cc << "\", \"" << esc(host_cc) << "\" },\n";
+		istr << "			{ \"" << ctor::cfg::host_cxx << "\", \"" << esc(host_cxx) << "\" },\n";
+		istr << "			{ \"" << ctor::cfg::host_ar << "\", \"" << esc(host_ar) << "\" },\n";
+		istr << "			{ \"" << ctor::cfg::host_ld << "\", \"" << esc(host_ld) << "\" },\n";
+		istr << "			{ \"" << ctor::cfg::build_cc << "\", \"" << esc(build_cc) << "\" },\n";
+		istr << "			{ \"" << ctor::cfg::build_cxx << "\", \"" << esc(build_cxx) << "\" },\n";
+		istr << "			{ \"" << ctor::cfg::build_ar << "\", \"" << esc(build_ar) << "\" },\n";
+		istr << "			{ \"" << ctor::cfg::build_ld << "\", \"" << esc(build_ld) << "\" },\n";
 		if(!ctor_includedir.empty())
 		{
-			istr << "			{ \"" << ctor::cfg::ctor_includedir << "\", \"" << ctor_includedir << "\" },\n";
+			istr << "			{ \"" << ctor::cfg::ctor_includedir << "\", \"" << esc(ctor_includedir) << "\" },\n";
 			ctor::includedir = ctor_includedir;
 		}
 		if(!ctor_libdir.empty())
 		{
-			istr << "			{ \"" << ctor::cfg::ctor_libdir << "\", \"" << ctor_libdir << "\" },\n";
+			istr << "			{ \"" << ctor::cfg::ctor_libdir << "\", \"" << esc(ctor_libdir) << "\" },\n";
 			ctor::libdir = ctor_libdir;
 		}
 
@@ -535,7 +536,7 @@ int regenerateCache(ctor::settings& settings,
 
 		for(const auto& ext : externalConfigs)
 		{
-			istr << "			{ \"" << ext.name << "\", {\n";
+			istr << "			{ \"" << esc(ext.name) << "\", {\n";
 			ctor::flags resolved_flags;
 			if(std::holds_alternative<ctor::external_manual>(ext.external))
 			{
diff --git a/src/util.cc b/src/util.cc
index 601fd54..08a135f 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -188,3 +188,20 @@ ctor::target_type target_type_from_extension(const std::filesystem::path& file)
 
 	return ctor::target_type::unknown;
 }
+
+std::string esc(const std::string& in)
+{
+	std::string out;
+	for(auto c : in)
+	{
+		switch(c)
+		{
+		case '\\': out += "\\\\"; break;
+		case '"': out += "\\\""; break;
+		default:
+			out += c;
+			break;
+		}
+	}
+	return out;
+}
diff --git a/src/util.h b/src/util.h
index 45f69d4..3ebef41 100644
--- a/src/util.h
+++ b/src/util.h
@@ -22,3 +22,5 @@ void append(T& a, const T& b)
 }
 
 ctor::target_type target_type_from_extension(const std::filesystem::path& file);
+
+std::string esc(const std::string& in);
-- 
cgit v1.2.3