Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Safer ReadVarBytes #511

Closed
wants to merge 4 commits into from
Closed

Conversation

shargon
Copy link
Member

@shargon shargon commented Dec 8, 2018

No description provided.

igormcoelho
igormcoelho previously approved these changes Dec 8, 2018
neo/IO/Helper.cs Outdated
return reader.ReadBytes((int)reader.ReadVarInt((ulong)max));
max = (int)reader.ReadVarInt((ulong)max);

if (reader.BaseStream.CanSeek)
Copy link
Contributor

Choose a reason for hiding this comment

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

If Stream supports seeking, update maximum to maximum seekable data. Nice!

@igormcoelho
Copy link
Contributor

igormcoelho commented Dec 9, 2018

Shargon, I added some tests that help validating this part. Feel free to remove them, if not necessary (but I think they are 😉 )

igormcoelho
igormcoelho previously approved these changes Dec 9, 2018
@igormcoelho
Copy link
Contributor

igormcoelho commented Dec 9, 2018

I think that we never use and don't need so much memory in any Neo process. Perhaps, a lower limit such as 16MB (as used in other methods 0x10000) or half int (~1GB) could be enforced in this case. For example, we could add if( max > 0x10000 ) throw Exception or if( max > Int32.MaxValue / 2 ) throw Exception... if well documented on the method.

neo/IO/Helper.cs Outdated

if (reader.BaseStream.CanSeek)
{
max = Math.Min((int)(reader.BaseStream.Length - reader.BaseStream.Position), max);
Copy link
Member

Choose a reason for hiding this comment

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

This can result in the reading of truncated data.

0x08123456

You should throw an exception instead of returning 0x123456.

Copy link
Member Author

Choose a reason for hiding this comment

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

Now is returned the data truncated, i do this for prevent the logic change

Copy link
Member

Choose a reason for hiding this comment

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

But reading truncated data is not the expected behavior of this function and can cause errors elsewhere.

@shargon
Copy link
Member Author

shargon commented Dec 9, 2018

@igormcoelho you left one 00 :P
But this could be a solution, maybe we can check if is higher than the max 0x1000000 (16 Mb)

@igormcoelho
Copy link
Contributor

Truncate or not to truncate? That's the question 🤔 💀
I agree with Erik, it's better an exception, ;f possible. We should create SafeReadBytes function and use it instead of ReadBytes everywhere then.

@erikzhang
Copy link
Member

What's the difference between this and the old implemention?

@shargon
Copy link
Member Author

shargon commented Dec 10, 2018

@erikzhang This fix a error mentioned in #Neo-Security channel

return reader.ReadBytes((int)reader.ReadVarInt((ulong)max));
max = (int)reader.ReadVarInt((ulong)max);

if (reader.BaseStream.CanSeek && (reader.BaseStream.Length - reader.BaseStream.Position) < max)
Copy link
Member

Choose a reason for hiding this comment

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

If reader.BaseStream.CanSeek == false, it is the same as the original implemention. We should limit max.

Copy link
Member

Choose a reason for hiding this comment

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

I checked everywhere, the maximum max is 16MB, no problem.

Copy link
Member

Choose a reason for hiding this comment

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

So the fix should be in neo-vm.

Copy link
Member

Choose a reason for hiding this comment

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

case OpCode.PUSHDATA4:
{
if (CurrentContext.InstructionPointer + 4 >= CurrentContext.Script.Length)
return false;
uint length = CurrentContext.Script.ToUInt32(CurrentContext.InstructionPointer + 1);
if (length > MaxItemSize) return false;
return true;
}

The stack element has been limited to 1MB here.

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right

@shargon
Copy link
Member Author

shargon commented Dec 10, 2018

Closed because the fix should be on NeoVM

@shargon shargon closed this Dec 10, 2018
@shargon shargon deleted the safe-readvar branch December 10, 2018 11:37
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