Skip to content

Commit 65e23ff

Browse files
committed
CommonIO: Make readFile() check if the file is not a directory and if not fail with a sensible exception rather than std::length_error
1 parent cbf1c3a commit 65e23ff

File tree

6 files changed

+29
-0
lines changed

6 files changed

+29
-0
lines changed

libsolutil/CommonIO.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,17 @@ namespace
4343
template <typename T>
4444
inline T readFile(std::string const& _file)
4545
{
46+
assertThrow(boost::filesystem::exists(_file), FileNotFound, _file);
47+
48+
// ifstream does not always fail when the path leads to a directory. Instead it might succeed
49+
// with tellg() returning a nonsensical value so that std::length_error gets raised in resize().
50+
assertThrow(boost::filesystem::is_regular_file(_file), NotAFile, _file);
51+
4652
T ret;
4753
size_t const c_elementSize = sizeof(typename T::value_type);
4854
std::ifstream is(_file, std::ifstream::binary);
55+
56+
// Technically, this can still fail even though we checked above because FS content can change at any time.
4957
assertThrow(is, FileNotFound, _file);
5058

5159
// get length of file:

libsolutil/CommonIO.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace solidity::util
3333

3434
/// Retrieve and returns the contents of the given file as a std::string.
3535
/// If the file doesn't exist, it will throw a FileNotFound exception.
36+
/// If the file exists but is not a regular file, it will throw NotAFile exception.
3637
/// If the file is empty, returns an empty string.
3738
std::string readFileAsString(std::string const& _file);
3839

libsolutil/Exceptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ DEV_SIMPLE_EXCEPTION(InvalidAddress);
4949
DEV_SIMPLE_EXCEPTION(BadHexCharacter);
5050
DEV_SIMPLE_EXCEPTION(BadHexCase);
5151
DEV_SIMPLE_EXCEPTION(FileNotFound);
52+
DEV_SIMPLE_EXCEPTION(NotAFile);
5253
DEV_SIMPLE_EXCEPTION(DataTooLong);
5354
DEV_SIMPLE_EXCEPTION(StringTooLong);
5455

solc/CommandLineInterface.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,10 @@ bool CommandLineInterface::parseLibraryOption(string const& _input)
668668
{
669669
// Should not happen if `fs::is_regular_file` is correct.
670670
}
671+
catch (NotAFile const&)
672+
{
673+
// Should not happen if `fs::is_regular_file` is correct.
674+
}
671675

672676
vector<string> libraries;
673677
boost::split(libraries, data, boost::is_space() || boost::is_any_of(","), boost::token_compress_on);
@@ -1263,6 +1267,11 @@ bool CommandLineInterface::processInput()
12631267
serr() << "File not found: " << jsonFile << endl;
12641268
return false;
12651269
}
1270+
catch (NotAFile const&)
1271+
{
1272+
serr() << "Not a regular file: " << jsonFile << endl;
1273+
return false;
1274+
}
12661275
}
12671276
StandardCompiler compiler(m_fileReader.reader());
12681277
sout() << compiler.compile(std::move(input)) << endl;

test/tools/yulopti.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,11 @@ Allowed options)",
282282
cerr << "File not found:" << _exception.comment() << endl;
283283
return 1;
284284
}
285+
catch (NotAFile const& _exception)
286+
{
287+
cerr << "Not a regular file:" << _exception.comment() << endl;
288+
return 1;
289+
}
285290

286291
if (arguments.count("input-file"))
287292
YulOpti{}.runInteractive(input);

test/tools/yulrun.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ Allowed options)",
148148
cerr << "File not found: " << path << endl;
149149
return 1;
150150
}
151+
catch (NotAFile const&)
152+
{
153+
cerr << "Not a regular file: " << path << endl;
154+
return 1;
155+
}
151156
}
152157
else
153158
input = readStandardInput();

0 commit comments

Comments
 (0)