1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-22 17:18:39 +00:00

Ensure that null C strings do not break logging (#15255)

This commit is contained in:
paradust7 2024-10-12 13:34:24 -07:00 committed by GitHub
parent 4e6e8b7bf1
commit 2188adc0f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 225 additions and 73 deletions

View file

@ -32,21 +32,60 @@ class StreamProxy {
public:
StreamProxy(std::ostream *os) : m_os(os) { }
static void fix_stream_state(std::ostream &os);
template<typename T>
StreamProxy& operator<<(T&& arg) {
StreamProxy& operator<<(T&& arg)
{
if (m_os) {
if (!m_os->good())
fix_stream_state(*m_os);
*m_os << std::forward<T>(arg);
}
return *this;
}
StreamProxy& operator<<(std::ostream& (*manip)(std::ostream&)) {
StreamProxy& operator<<(std::ostream& (*manip)(std::ostream&))
{
if (m_os) {
if (!m_os->good())
fix_stream_state(*m_os);
*m_os << manip;
}
return *this;
}
private:
template<typename T>
StreamProxy& emit_with_null_check(T&& arg)
{
// These calls explicitly use the templated version of operator<<,
// so that they won't use the overloads created by ADD_NULL_CHECK.
if (arg == nullptr)
return this->operator<< <const char*> ("(null)");
else
return this->operator<< <T>(std::forward<T>(arg));
}
public:
// Add specific overrides for operator<< which check for NULL string
// pointers. This is undefined behavior in the C++ spec, so emit "(null)"
// instead. These are method overloads, rather than template specializations.
#define ADD_NULL_CHECK(_type) \
StreamProxy& operator<<(_type arg) \
{ \
return emit_with_null_check(std::forward<_type>(arg)); \
}
ADD_NULL_CHECK(char*)
ADD_NULL_CHECK(unsigned char*)
ADD_NULL_CHECK(signed char*)
ADD_NULL_CHECK(const char*)
ADD_NULL_CHECK(const unsigned char*)
ADD_NULL_CHECK(const signed char*)
#undef ADD_NULL_CHECK
private:
std::ostream *m_os;
};