Merge pull request #10199 from ethereum/readfile

[CLI] Improve error handling of missing/unwriteable files
This commit is contained in:
chriseth 2020-11-10 13:50:40 +01:00 committed by GitHub
commit eaba9a680a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 55 additions and 9 deletions

View File

@ -4,6 +4,8 @@ Language Features:
* Ability to select the abi coder using ``pragma abicoder v1`` and ``pragma abicoder v2``.
Compiler Features:
* Command Line Interface: Report error if file could not be read in ``--standard-json`` mode.
* Command Line interface: Report proper error for each output file which could not be written. Previously an exception was thrown, and execution aborted, on the first error.
* SMTChecker: Add division by zero checks in the CHC engine.
* SMTChecker: Support ``selector`` for expressions with value known at compile-time.
* Command Line Interface: New option ``--model-checker-timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker.

View File

@ -47,8 +47,7 @@ inline T readFile(std::string const& _file)
T ret;
size_t const c_elementSize = sizeof(typename T::value_type);
std::ifstream is(_file, std::ifstream::binary);
if (!is)
return ret;
assertThrow(is, FileNotFound, _file);
// get length of file:
is.seekg(0, is.end);

View File

@ -32,7 +32,8 @@ namespace solidity::util
{
/// Retrieve and returns the contents of the given file as a std::string.
/// If the file doesn't exist or isn't readable, returns an empty container / bytes.
/// If the file doesn't exist, it will throw a FileNotFound exception.
/// If the file is empty, returns an empty string.
std::string readFileAsString(std::string const& _file);
/// Retrieve and returns the contents of standard input (until EOF).

View File

@ -48,7 +48,7 @@ private:
DEV_SIMPLE_EXCEPTION(InvalidAddress);
DEV_SIMPLE_EXCEPTION(BadHexCharacter);
DEV_SIMPLE_EXCEPTION(BadHexCase);
DEV_SIMPLE_EXCEPTION(FileError);
DEV_SIMPLE_EXCEPTION(FileNotFound);
DEV_SIMPLE_EXCEPTION(DataTooLong);
DEV_SIMPLE_EXCEPTION(StringTooLong);

View File

@ -614,6 +614,7 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings()
continue;
}
// NOTE: we ignore the FileNotFound exception as we manually check above
m_sourceCodes[infile.generic_string()] = readFileAsString(infile.string());
path = boost::filesystem::canonical(infile).string();
}
@ -643,6 +644,10 @@ bool CommandLineInterface::parseLibraryOption(string const& _input)
{
// Thrown e.g. if path is too long.
}
catch (FileNotFound const&)
{
// Should not happen if `fs::is_regular_file` is correct.
}
vector<string> libraries;
boost::split(libraries, data, boost::is_space() || boost::is_any_of(","), boost::token_compress_on);
@ -738,7 +743,11 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da
ofstream outFile(pathName);
outFile << _data;
if (!outFile)
BOOST_THROW_EXCEPTION(FileError() << errinfo_comment("Could not write to file: " + pathName));
{
serr() << "Could not write to file \"" << pathName << "\"." << endl;
m_error = true;
return;
}
}
void CommandLineInterface::createJson(string const& _fileName, string const& _json)
@ -1146,6 +1155,7 @@ bool CommandLineInterface::processInput()
if (!boost::filesystem::is_regular_file(canonicalPath))
return ReadCallback::Result{false, "Not a valid file."};
// NOTE: we ignore the FileNotFound exception as we manually check above
auto contents = readFileAsString(canonicalPath.string());
m_sourceCodes[path.generic_string()] = contents;
return ReadCallback::Result{true, contents};
@ -1232,7 +1242,17 @@ bool CommandLineInterface::processInput()
if (jsonFile.empty())
input = readStandardInput();
else
input = readFileAsString(jsonFile);
{
try
{
input = readFileAsString(jsonFile);
}
catch (FileNotFound const&)
{
serr() << "File not found: " << jsonFile << endl;
return false;
}
}
StandardCompiler compiler(fileReader);
sout() << compiler.compile(std::move(input)) << endl;
return true;

View File

@ -0,0 +1 @@
--standard-json

View File

@ -0,0 +1 @@
File not found: standard_file_not_found/input.sol

View File

@ -0,0 +1 @@
1

View File

@ -20,6 +20,7 @@
*/
#include <libsolutil/CommonIO.h>
#include <libsolutil/Exceptions.h>
#include <liblangutil/ErrorReporter.h>
#include <liblangutil/Scanner.h>
#include <libyul/AsmAnalysis.h>
@ -243,8 +244,18 @@ Allowed options)",
}
string input;
try
{
input = readFileAsString(arguments["input-file"].as<string>());
}
catch (FileNotFound const& _exception)
{
cerr << "File not found:" << _exception.comment() << endl;
return 1;
}
if (arguments.count("input-file"))
YulOpti{}.runInteractive(readFileAsString(arguments["input-file"].as<string>()));
YulOpti{}.runInteractive(input);
else
cout << options;

View File

@ -35,6 +35,7 @@
#include <libsolutil/CommonIO.h>
#include <libsolutil/CommonData.h>
#include <libsolutil/Exceptions.h>
#include <boost/program_options.hpp>
@ -137,10 +138,19 @@ Allowed options)",
else
{
string input;
if (arguments.count("input-file"))
for (string path: arguments["input-file"].as<vector<string>>())
input += readFileAsString(path);
{
try
{
input += readFileAsString(path);
}
catch (FileNotFound const&)
{
cerr << "File not found: " << path << endl;
return 1;
}
}
else
input = readStandardInput();