Reject unreadable UCE source units
This commit is contained in:
+34
-2
@@ -2,8 +2,10 @@
|
||||
#include "compiler-parser.h"
|
||||
#include "hash.h"
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fcntl.h>
|
||||
#include <mutex>
|
||||
@@ -50,6 +52,7 @@ struct UnitSourceSignatureEntry
|
||||
u64 modified_ns = 0;
|
||||
u64 changed_ns = 0;
|
||||
u64 size = 0;
|
||||
bool readable = false;
|
||||
String content_hash;
|
||||
StringList loaded_paths;
|
||||
};
|
||||
@@ -128,6 +131,18 @@ StringList compiler_unit_load_paths(String file_name, String content)
|
||||
return(paths);
|
||||
}
|
||||
|
||||
bool compiler_source_readable(String file_name, const struct stat& info, int* read_error = 0)
|
||||
{
|
||||
int error = 0;
|
||||
if((info.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0)
|
||||
error = EACCES;
|
||||
else if(access(file_name.c_str(), R_OK) != 0)
|
||||
error = errno;
|
||||
if(read_error)
|
||||
*read_error = error;
|
||||
return(error == 0);
|
||||
}
|
||||
|
||||
UnitSourceSignatureEntry compiler_unit_source_entry(String file_name)
|
||||
{
|
||||
struct stat info;
|
||||
@@ -137,10 +152,11 @@ UnitSourceSignatureEntry compiler_unit_source_entry(String file_name)
|
||||
entry.modified_ns = (u64)info.st_mtim.tv_sec * 1000000000ull + (u64)info.st_mtim.tv_nsec;
|
||||
entry.changed_ns = (u64)info.st_ctim.tv_sec * 1000000000ull + (u64)info.st_ctim.tv_nsec;
|
||||
entry.size = (u64)info.st_size;
|
||||
entry.readable = compiler_source_readable(file_name, info);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(unit_source_signature_cache_mutex);
|
||||
auto cached = unit_source_signature_cache.find(file_name);
|
||||
if(cached != unit_source_signature_cache.end() && cached->second.modified_ns == entry.modified_ns && cached->second.changed_ns == entry.changed_ns && cached->second.size == entry.size)
|
||||
if(cached != unit_source_signature_cache.end() && cached->second.modified_ns == entry.modified_ns && cached->second.changed_ns == entry.changed_ns && cached->second.size == entry.size && cached->second.readable == entry.readable)
|
||||
return(cached->second);
|
||||
}
|
||||
String content = file_get_contents(file_name);
|
||||
@@ -165,7 +181,7 @@ void compiler_append_unit_source_signature(String file_name, std::set<String>& v
|
||||
visited.insert(normalized);
|
||||
|
||||
UnitSourceSignatureEntry entry = compiler_unit_source_entry(normalized);
|
||||
signature += normalized + ":" + entry.content_hash + "\n";
|
||||
signature += normalized + ":" + entry.content_hash + (entry.readable ? String("") : String(":unreadable")) + "\n";
|
||||
for(String loaded : entry.loaded_paths)
|
||||
compiler_append_unit_source_signature(loaded, visited, signature);
|
||||
}
|
||||
@@ -793,6 +809,22 @@ void compile_shared_unit(Request* context, SharedUnit* su)
|
||||
compiler_record_compile_result(su, time_precise() - comp_start, false, "missing_source", su->compiler_messages);
|
||||
return;
|
||||
}
|
||||
struct stat source_info;
|
||||
int read_error = 0;
|
||||
bool source_readable = stat(su->file_name.c_str(), &source_info) == 0 && compiler_source_readable(su->file_name, source_info, &read_error);
|
||||
if(!source_readable && read_error == 0)
|
||||
read_error = errno == 0 ? ENOENT : errno;
|
||||
if(!source_readable)
|
||||
{
|
||||
su->compiler_messages = "source file is not readable (" + su->file_name + "): " + std::strerror(read_error);
|
||||
file_put_contents(su->compile_output_file_name, su->compiler_messages + "\n");
|
||||
file_put_contents(su->wasm_check_file_name, su->compiler_messages + "\n");
|
||||
file_put_contents(su->meta_file_name, compiler_unit_metadata_text(context, su));
|
||||
file_unlink(su->wasm_name);
|
||||
compiler_record_compile_result(su, time_precise() - comp_start, false, "compile_error", su->compiler_messages);
|
||||
printf("%s \n", compiler_format_compile_failure(su, su->compiler_messages).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
shell_exec("mkdir -p " + shell_escape(su->pre_path));
|
||||
file_put_contents(su->pre_path + "/" + su->pre_file_name, preprocess_shared_unit(context, su));
|
||||
|
||||
Reference in New Issue
Block a user