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

add recursion limit #248

Merged
merged 3 commits into from
Oct 31, 2017
Merged

Conversation

BusyJay
Copy link
Contributor

@BusyJay BusyJay commented Oct 27, 2017

Provide a way to configure recursion limit so invalid messages or deeply nested messages won't lead to stack overflow, which has no way to recover.

@@ -31,6 +31,9 @@ use buf_read_iter::BufReadIter;
// `CodedOutputStream` wraps `BufWriter`, it often skips double buffering.
const OUTPUT_STREAM_BUFFER_SIZE: usize = 8 * 1024;

// Default recursion level limit.
const DEFAULT_RECURSION_LIMIT: isize = 100;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

100 is just copied from C++ implementation. If you think it's too small, please let me know.

Copy link
Owner

Choose a reason for hiding this comment

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

Thanks for the explanation. Could you please paste the explanation into the source comments?

}

/// Set the recursion limit.
pub fn set_recursion_limit(&mut self, limit: isize) {
Copy link
Owner

@stepancheg stepancheg Oct 30, 2017

Choose a reason for hiding this comment

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

Parameter should be u32 probably

  • to avoid misunderstanding (negative value is meaningless)
  • should be platform-independent

@@ -121,24 +124,54 @@ pub mod wire_format {

pub struct CodedInputStream<'a> {
source: BufReadIter<'a>,
recursion_budget: isize,
Copy link
Owner

Choose a reason for hiding this comment

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

I think it should be i32 to make it platform-independent.

}

// Only for internal tracing
#[doc(hidden)]
Copy link
Owner

Choose a reason for hiding this comment

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

AFAIU this function can be pub(crate) instead of public+hidden.

#[inline]
pub fn incr_recursion(&mut self) -> ProtobufResult<()> {
self.recursion_budget -= 1;
if self.recursion_budget < 0 {
Copy link
Owner

Choose a reason for hiding this comment

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

Looks like there's a bug here: if we hit recursion_limit, we've lost the budget. Should probably be:

if self.recursion_budget <= 0 { return error; }
self.recursion_budget -= 1;
Ok(())

assert_eq!(test3, t);

is = CodedInputStream::from_bytes(&bytes);
is.set_recursion_limit(0);
Copy link
Owner

Choose a reason for hiding this comment

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

Ideally this should be tested with recursion level = 3 or something like that, so that read with 2 is OK and read with 3 returns error to really check that code didn't mess with signs or something like that.

Copy link
Owner

@stepancheg stepancheg left a comment

Choose a reason for hiding this comment

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

Thank you for patch! It's important missing part of the implementation.

I've added a couple of suggestions, would be mind addressing them?

@stepancheg
Copy link
Owner

Thank you!

@stepancheg stepancheg closed this Oct 31, 2017
@stepancheg stepancheg reopened this Oct 31, 2017
@stepancheg stepancheg merged commit 51f50fb into stepancheg:master Oct 31, 2017
@BusyJay BusyJay deleted the set-recurse-limit branch October 31, 2017 10:54
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.

2 participants