Error Handling¶
Introduction¶
LIEF manages errors using:
Exceptions (deprecated and removed since LIEF 0.13.0)
It turns out that using C++ exceptions (and RTTI) was not the best design choice, as LIEF, as a library, can be used in a -fno-exceptions context. Consequently, we moved to a mechanism based on the ResultOrError idiom. This idiom is similar to those found in LLVM with llvm::ErrorOr and in Rust with std::result. LIEF uses a std::expected-like interface to handle errors. Since this interface is only available in C++23, we rely on TartanLlama/expected, which provides this interface for C++11/C++17.
Functions using this idiom return a LIEF::result, which wraps either the successful result or an error.
The user can process this result as follows:
result<PE_TYPE> pe_type = PE::get_type("/tmp/NotPE.elf");
if (pe_type) {
PE_TYPE effective_type = pe_type.value();
} else {
lief_errors err = as_lief_err(pe_type);
}
In the case of Python, we leverage the dynamic features of the language to return either the expected value or an error if the function fails. For instance, in previous versions of lief.PE.get_type(), the implementation raised an exception to inform the user:
try:
pe_type = lief.PE.get_type("/tmp/NotPE.elf")
# If it does not fail, pe_type handles a lief.PE.PE_TYPE object
except Exception as e:
print(f"Error: {e}")
With the new implementation that relies on the ResultOrError idiom, the function returns the lief.PE.PE_TYPE value if everything is correct, and returns a lief.lief_errors in case of a processing error.
The user can handle this new interface by using the isinstance() function or by comparing the value with a lief.lief_errors attribute:
pe_type = lief.PE.get_type("/tmp/NotPE.elf")
if pe_type == lief.lief_errors.file_error:
print("File error")
elif isinstance(pe_type, lief.lief_errors):
print("Another kind of error")
else:
print(f"No error, type is: {pe_type}")
API¶
C++¶
- template<typename T>
class result : public tl::expected<T, lief_errors>¶ Wrapper that contains an Object (
T) or an error.The tl/expected implementation exposes the method
value()to access the underlying object (if no error)Typical usage is:
result<int> intval = my_function(); if (intval) { int val = intval.value(); } else { // There is an error std::cout << get_error(intval).message() << "\n"; }
See https://tl.tartanllama.xyz/en/latest/api/expected.html for more details
Public Functions
- inline result(tl::expected<T, lief_errors> e)¶
- inline result(tl::expected<T, lief_errors> e)¶
- template<class T>
lief_errors LIEF::as_lief_err(result<T> &err)¶ Return the lief_errors when the provided
result<T>is an error.
- enum class lief_errors : uint32_t¶
LIEF error codes definition.
Values:
- enumerator read_error = 1¶
- enumerator not_found¶
- enumerator not_implemented¶
- enumerator not_supported¶
- enumerator corrupted¶
- enumerator conversion_error¶
- enumerator read_out_of_bound¶
- enumerator asn1_bad_tag¶
- enumerator file_error¶
- enumerator file_format_error¶
- enumerator parsing_error¶
- enumerator build_error¶
- enumerator data_too_large¶
- enumerator require_extended_version¶
- enumerator inconsistent¶
- enumerator runtime_error¶
- enumerator read_error = 1¶
- class ok_error_t : public LIEF::result<ok_t>¶
Opaque structure that is used by LIEF to avoid writing
result<void> f(...). Instead, it makes the output explicit such as:ok_error_t process() { if (fail) { return make_error_code(...); } return ok(); }
- inline ok_t LIEF::ok()¶
Return success for function with return type ok_error_t.
- struct ok_t¶
Opaque structure used by ok_error_t.
Python¶
- class lief.lief_errors(*values)¶
Bases:
EnumEnum class which represents an error generated by LIEF’s functions
- asn1_bad_tag = 8¶
- build_error = 12¶
- conversion_error = 6¶
- corrupted = 5¶
- data_too_large = 13¶
- file_error = 9¶
- file_format_error = 10¶
- inconsistent = 15¶
- not_found = 2¶
- not_implemented = 3¶
- not_supported = 4¶
- parsing_error = 11¶
- read_error = 1¶
- read_out_of_bound = 7¶
- require_extended_version = 14¶
- runtime_error = 16¶
- class lief.ok_t¶
Bases:
objectOpaque value returned when a void function is executed successfully.
- class lief.ok_error_t¶
Bases:
objectReturn either:
ok_t(success) orlief_errors(error)- property error lief.lief_errors¶
- property is_error bool¶
- property is_value bool¶