Skip to content

Fix server crash when read a malformed replication segment#9055

Open
XaBbl4 wants to merge 2 commits into
FirebirdSQL:masterfrom
XaBbl4:fix_crash_when_read_repl_segment
Open

Fix server crash when read a malformed replication segment#9055
XaBbl4 wants to merge 2 commits into
FirebirdSQL:masterfrom
XaBbl4:fix_crash_when_read_repl_segment

Conversation

@XaBbl4

@XaBbl4 XaBbl4 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

If a segment has some damage and it falls on the length of a string or the position of an atom, then the server crash with SIGSEGV, instead of output an correct error

Comment thread src/jrd/replication/Applier.cpp Outdated
const auto length = getInt32();
const ULONG length = static_cast<ULONG>(getInt32());

if (m_data + length > m_end)

@aafemt aafemt Jun 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to leave length as is and use a correct condition instead: (length <= 0 || m_end - m_data < length).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this, but in the case of an unsigned string, the length might be longer. In what case might it be useful to have a negative string length?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, back length as is in getString.
Also add check length in defineAtom.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should ask @dyemanov why he chose signed result for getIntXX functions.

May be you are right about maximum string length. In this case the right condition avoiding overflow on the end of address space still would be (m_end - m_data < length). Only the last gigabyte is reserved by OSes IIRC so if the buffer by change is just below it, m_data + length may be a little above zero causing false negative.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe zero-sized string is allowed. @dyemanov ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should ask @dyemanov why he chose signed result for getIntXX functions.

I tried to make getters generic, as I couldn't predict whether signed numbers could ever appear inside the replication protocol or not. Given that numbers > 2^31 are not expected this looked safe.

… was.

Also add a length check to the defineAtom function.
const auto pos = getInt32();
const ULONG pos = static_cast<ULONG>(getInt32());

if (pos >= m_atoms.getCount())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer explicit checks with a signed pos:

if (pos < 0 || pos >= m_atoms.getCount())

const auto length = getInt32();

if (m_data + length > m_end)
if (length <= 0 || m_end - m_data < length)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd allow zero-length strings even if it looks impossible now.

const auto pos = getInt32();
const ULONG pos = static_cast<ULONG>(getInt32());

if (pos >= m_atoms.getCount())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

void defineAtom()
{
const auto length = getByte();
if (length <= 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants