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

utils: add s2n_result implementation #1872

Merged
merged 1 commit into from
May 12, 2020
Merged

Conversation

camshaft
Copy link
Contributor

@camshaft camshaft commented May 8, 2020

Please note that while we are transitioning from travis-ci to AWS CodeBuild, some tests are run on each platform. Non-AWS contributors will temporarily be unable to see CodeBuild results. We apologize for the inconvenience.

Issue # (if available):
Part 1 for #1782 and #1783

Description of changes:

The goal of s2n_result is to provide a strongly-typed error signal value, which provides the compiler with enough information to catch bugs.

Historically, s2n has used int to signal errors. This has caused a few issues:

GUARD in a function returning integer types

There is no compiler error if GUARD(nested_call()); is used in a function that is meant to return integer type - not a error signal.

uint8_t s2n_answer_to_the_ultimate_question() {
  GUARD(s2n_sleep_for_years(7500000));
  return 42;
}

In this function we intended to return a uint8_t but used a GUARD which will return -1 if the call fails. This can lead to very subtle bugs.

GUARDing a function returning any integer type

There is no compiler error if GUARD(nested_call()); is used on a function that doesn't actually return an error signal

int s2n_deep_thought() {
  GUARD(s2n_answer_to_the_ultimate_question());
  return 0;
}

In this function we intended guard against a failure of s2n_answer_to_the_ultimate_question but that function doesn't actually return an error signal. Again, this can lead to sublte
bugs.

Ignored error signals

Without the warn_unused_result function attribute, the compiler provides no warning when forgetting to GUARD a function. Missing a GUARD can lead to subtle bugs.

int s2n_answer_to_the_ultimate_question() {
  s2n_sleep_for_years(7500000); // <- THIS SHOULD BE GUARDED!!!
  return 42;
}

Solution

s2n_result provides a newtype declaration, which is popular in languages like Haskell and Rust.

Functions that return S2N_RESULT are automatically marked with the warn_unused_result attribute, which ensures they are GUARDed.

Follow up

Over the next week I will gradually be moving functions to return S2N_RESULT instead of int.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

utils/s2n_result.c Show resolved Hide resolved
utils/s2n_result.c Outdated Show resolved Hide resolved
utils/s2n_result.h Outdated Show resolved Hide resolved
utils/s2n_result.h Show resolved Hide resolved
@baldwinmatt
Copy link
Contributor

Nice!

utils/s2n_result.c Outdated Show resolved Hide resolved
@zz85
Copy link
Contributor

zz85 commented May 8, 2020

first contribution! one thing to note: functions in fuzz tests are unguarded, if we enforce compiler warnings, we could consider adding FUZZ_GUARD() macros.

@camshaft
Copy link
Contributor Author

camshaft commented May 8, 2020

Ignoring an error signal, even in fuzz tests, is a bad idea. Having a guard macro that crashes might be the way to go there. But we can address that once I get to those.

@camshaft camshaft force-pushed the s2n_result_def branch 5 times, most recently from 2946bd5 to 6e0ca0f Compare May 9, 2020 01:12
utils/s2n_map.c Outdated Show resolved Hide resolved
tls/s2n_config.c Outdated Show resolved Hide resolved
@camshaft camshaft force-pushed the s2n_result_def branch 4 times, most recently from 466dc39 to 8c4dad7 Compare May 11, 2020 20:15
utils/s2n_result.h Outdated Show resolved Hide resolved
@codecov-io
Copy link

Codecov Report

Merging #1872 into master will increase coverage by 0.00%.
The diff coverage is 97.26%.

@@           Coverage Diff           @@
##           master    #1872   +/-   ##
=======================================
  Coverage   81.44%   81.45%           
=======================================
  Files         226      228    +2     
  Lines       16905    16921   +16     
=======================================
+ Hits        13769    13783   +14     
- Misses       3136     3138    +2     

Impacted file tree graph

Copy link
Contributor

@colmmacc colmmacc left a comment

Choose a reason for hiding this comment

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

Type system based checking in C! Love this.

Copy link
Contributor

@zz85 zz85 left a comment

Choose a reason for hiding this comment

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

would be nice to add to the development/usage guide which macros should be used, and how to use them during the transition phase

GUARD_RESULT() - should use only with new s2n_result functions and returns s2n_result
GUARD_AS_RESULT() - guard old guard functions but returns new s2n_results
GUARD_AS_POSIX() - guard new s2n_result function but returns old guard int

@camshaft camshaft merged commit 920b384 into aws:master May 12, 2020
@camshaft camshaft deleted the s2n_result_def branch May 12, 2020 19:25
@camshaft
Copy link
Contributor Author

I'll add the guide in a separate PR

Copy link
Contributor

@baldwinmatt baldwinmatt left a comment

Choose a reason for hiding this comment

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

Lgtm! Looking forward to this!

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.

8 participants