GithubHelp home page GithubHelp logo

saltyrtc / saltyrtc-client-rs Goto Github PK

View Code? Open in Web Editor NEW
34.0 34.0 5.0 669 KB

SaltyRTC Rust implementation.

License: Apache License 2.0

Rust 99.22% Meson 0.10% C 0.68%
client rust saltyrtc signaling

saltyrtc-client-rs's People

Contributors

dbrgn avatar lgrahl avatar threema-danilo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

saltyrtc-client-rs's Issues

Support setting ping interval

As sent in the ClientAuth message.

If I remember correctly this is a purely server-side setting. Otherwise we'd probably have to put the ping change in the HandleAction, affecting #6.

Clean up API docs

  • Go through all public types, make sure that they really should be public
  • Make sure to document all types
  • Add #[deny(missing_docs)] (or whatever it's called) to the crate
  • Add some prose docs on the root page

Type safety: Handshake vs task loop

Currently the user can pass a WsClient and a SaltyClient instance to the task loop without going through the handshake.

Maybe we can prevent that?

Handle new-initiator/new-responder correctly

When a 'new-initiator' or 'new-responder' message has been received, the initiator/responder simply replaces the corresponding instance but does not reset its own state.

Due to a limitation of the implementation, after the task has kicked in, it should also...

  • drop the responder in case it is an initiator, and
  • close the connection normally in case it is a responder.

IncomingNonce vs OutgoingNonce

Similar to #9. Do we want to differentiate between an incoming and an outgoing nonce?

This could make handling the messages much more annoying, so right now I doubt that it's worth it. But we should verify that again.

PermanentKey vs SessionKey

Do we want to differentiate between permanent and session public keys using the type system? It could give us some additional safety guarantees, but might make handling a bit more complicated.

Simplify HandleAction

Originally I planned to make the HandleAction deal with all side effects. But now it only contains the Reply variant.

We should probably get rid of it, or convert it to a newtype wrapper.

Question: Programming language choice

Probably the wrong place to ask, but I've not found a better one. :/

Actually, I have just a short question out of curiosity. As far as I understand, this library is mainly for the iOS app of Threema.

Just wanted to ask why Rust has been chosen for this library and not Golang or Objective-C? I do not ask because I think one is better than the other (I have no Rust, Go or Objective-C experience), just because of curiosity. While following the development, I have however seen that Rust has some problems because of lacking stable crates. Golang is very good at networking and has stable libraries.

Use smallvec

In many cases (e.g. list of tasks) we can make use of the smallvec library to allocate small vectors on the stack instead of on the heap.

Write C FFI bindings

Note: When dealing with data structures, serializing them in Rust and deserializing them in C (with a zero-copy library like Flatbuffers or Cap'n Proto) might be a way to simplify FFI stuff. It would alow our API to communicate through a read_bytes and write_bytes function, without the usual FFI hassle.

On the other hand this would introduce yet another dependency, so as long as our interface is not too large, we should probably just stick to regular FFI.

Protocol Review

I have reviewed most of the protocol-related code to get an overview of the Rust client implementation. I identified the following potential issues that may need addressing (some definitely do, some are more of a question).

It may make sense to treat this as an umbrella issue and file separate issues for each when they are being tackled.

Findings

  • 1: Accept destination 0x00 indefinitely.
    • Location:
      fn validate_nonce_destination(&mut self, nonce: &Nonce) -> Result<(), ValidationError> {
      // A client MUST check that the destination address targets its
      // assigned identity (or `0x00` during authentication).
      if self.identity() == ClientIdentity::Unknown
      && !nonce.destination().is_unknown()
      && self.server_handshake_state() != ServerHandshakeState::New {
      // The first message received with a destination address different
      // to `0x00` SHALL be accepted as the client's assigned identity.
      // However, the client MUST validate that the identity fits its
      // role โ€“ initiators SHALL ONLY accept `0x01`. The identity MUST
      // be stored as the client's assigned identity.
      if nonce.destination().is_initiator() {
      self.common.identity = ClientIdentity::Initiator;
      debug!("Assigned identity: {}", self.identity());
      } else {
      return Err(ValidationError::Fail(
      format!("cannot assign address {} to initiator", nonce.destination())
      ));
      };
      }
      if nonce.destination() != self.identity().into() {
      return Err(ValidationError::Fail(
      format!("Bad destination: {} (our identity is {})", nonce.destination(), self.identity())
      ));
      }
      Ok(())
      }
      and
      fn validate_nonce_destination(&mut self, nonce: &Nonce) -> Result<(), ValidationError> {
      // A client MUST check that the destination address targets its
      // assigned identity (or `0x00` during authentication).
      if self.identity() == ClientIdentity::Unknown
      && !nonce.destination().is_unknown()
      && self.server_handshake_state() != ServerHandshakeState::New {
      // The first message received with a destination address different
      // to `0x00` SHALL be accepted as the client's assigned identity.
      // However, the client MUST validate that the identity fits its
      // role โ€“ responders SHALL ONLY an identity from the range
      // `0x02..0xff`. The identity MUST be stored as the client's
      // assigned identity.
      if nonce.destination().is_responder() {
      self.common.identity = ClientIdentity::Responder(nonce.destination().0);
      debug!("Assigned identity: {}", self.identity());
      } else {
      return Err(ValidationError::Fail(
      format!("cannot assign address {} to a responder", nonce.destination())
      ));
      };
      }
      if nonce.destination() != self.identity().into() {
      return Err(ValidationError::Fail(
      format!("Bad destination: {} (our identity is {})", nonce.destination(), self.identity())
      ));
      }
      Ok(())
      }
    • Proposal: None, yet. Unsure if this needs resolving.
  • 2: Reacts with protocol error when receiving a message from an unknown responder.
    • Fix in PR #59
  • 3: Does not remove the initiator/responder instance when it has received a 'disconnected' message.
    • Location:
      fn handle_disconnected(&mut self, msg: Disconnected) -> SignalingResult<Vec<HandleAction>> {
      debug!("--> Received disconnected from server");
      // An initiator who receives a 'disconnected' message SHALL validate
      // that the id field contains a valid responder address (0x02..0xff).
      if !msg.id.is_responder() {
      return Err(SignalingError::Protocol(
      "Received 'disconnected' message with non-responder id".into()
      ));
      }
      Ok(vec![HandleAction::Event(Event::Disconnected(msg.id.0))])
      }
      and
      fn handle_disconnected(&mut self, msg: Disconnected) -> SignalingResult<Vec<HandleAction>> {
      debug!("--> Received disconnected from server");
      // A responder who receives a 'disconnected' message SHALL validate
      // that the id field contains a valid initiator address (0x01).
      if !msg.id.is_initiator() {
      return Err(SignalingError::Protocol(
      "Received 'disconnected' message with non-initiator id".into()
      ));
      }
      Ok(vec![HandleAction::Event(Event::Disconnected(msg.id.0))])
      }
    • Proposal: Remove the instance. Tear down the task if it has already kicked in. (If the implementation cannot cope with further connections after the task kicked in, it may need to close.)
  • 4: When a new initiator is connecting via 'new-initiator', a responder simply replaces the initiator instance but does not reset its own state.
    • Location:
      fn handle_new_initiator(&mut self, _msg: NewInitiator) -> SignalingResult<Vec<HandleAction>> {
      debug!("--> Received new-initiator from server");
      let mut actions: Vec<HandleAction> = vec![];
      // A responder who receives a 'new-initiator' message MUST proceed by
      // deleting all currently cached information about and for the previous
      // initiator (such as cookies and the sequence numbers)...
      self.initiator = InitiatorContext::new(self.initiator.permanent_key);
      // ...and continue by sending a 'token' or 'key' client-to-client
      // message described in the Client-to-Client Messages section.
      let mut send_token = false;
      match self.common().auth_provider {
      Some(AuthProvider::Token(_)) => {
      send_token = true;
      },
      Some(AuthProvider::TrustedKey(_)) => {
      debug!("Trusted key available, skipping token message");
      },
      None => {
      return Err(SignalingError::Crash("No auth provider set".into()));
      },
      }
      if send_token {
      let old_auth_provider = mem::replace(&mut self.common_mut().auth_provider, None);
      if let Some(AuthProvider::Token(token)) = old_auth_provider {
      actions.push(self.send_token(token)?);
      } else {
      return Err(SignalingError::Crash("Auth provider is not a token".into()));
      }
      }
      actions.push(self.send_key()?);
      self.initiator.set_handshake_state(InitiatorHandshakeState::KeySent);
      Ok(actions)
      }
    • Issue: #61
    • Proposal: Close the connection immediately if the peer handshake has already been completed as this implementation cannot cope with multiple initiators. This must prevent any further interaction with/from the task.
  • 5: When a new responder is connecting via 'new-responder' with the same identity, an initiator simply replaces the responder instance but does not reset its own state.
    • Location:
      /// Handle an incoming [`NewResponder`](messages/struct.NewResponder.html) message.
      fn handle_new_responder(&mut self, msg: NewResponder) -> SignalingResult<Vec<HandleAction>> {
      debug!("--> Received new-responder ({}) from server", msg.id);
      // An initiator who receives a 'new-responder' message SHALL validate
      // that the id field contains a valid responder address (0x02..0xff).
      if !msg.id.is_responder() {
      return Err(SignalingError::InvalidMessage(
      "`id` field in new-responder message is not a valid responder address".into()
      ));
      }
      // Process responder
      match self.process_new_responder(msg.id)? {
      Some(drop_responder) => Ok(vec![drop_responder]),
      None => Ok(vec![]),
      }
      }
    • Issue: #61
    • Proposal: Drop new responders after the peer handshake has been completed. Do not process them.
  • 6: Peer messages are being handled when the server handshake is in progress.
  • 7: When a peer message is being handled, it does a sanity-check to ensure the message is not being sent from a server. But later, it tries to forward server messages.
    • Location:
      SignalingState::PeerHandshake if obox.nonce.source().is_server() =>
      self.handle_server_message(obox, None),
    • Proposal: Crash instead of handling the message.
  • 8: The task_supported_types seems unnecessary to me. The task should filter itself anyway.

The above checkboxes shall be ticked if the issue has been confirmed, resolved and a fix, including a test, has been merged, or alternatively in case it has been identified as a non-issue in which case an explanation needs to be added.

Notes

Having reviewed the JS and Java client as well, Cpt. Hindsight says that we should avoid using separate functions for handling inbound messages. The dispatching logic depending on states has been a weak point in all three clients and made the control flow complicated to follow. Alternative solutions would have to be explored.

Document testing

The tests require a server to run but they also require a certificate. This is not documented at the moment.

And perhaps add support for using a PEM for the certificate instead of DER.

fatal error: ncurses.h: No such file or directory

I can't build the example. cargo run --example chat -- initiator results in the following errors:

error: failed to run custom build command for `ncurses v5.99.0`
process didn't exit successfully: `/home/ben/saltyrtc-client-rs/target/debug/build/ncurses-1f9ca53704032ffe/build-script-build` (exit code: 101)
--- stdout
cargo:rerun-if-env-changed=PKG_CONFIG_PATH
cargo:rustc-link-lib=ncursesw
OPT_LEVEL = Some("0")
TARGET = Some("x86_64-unknown-linux-gnu")
HOST = Some("x86_64-unknown-linux-gnu")
CC_x86_64-unknown-linux-gnu = None
CC_x86_64_unknown_linux_gnu = None
HOST_CC = None
CC = None
CFLAGS_x86_64-unknown-linux-gnu = None
CFLAGS_x86_64_unknown_linux_gnu = None
HOST_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("true")
CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2")

/home/ben/saltyrtc-client-rs/target/debug/build/ncurses-97110365ef2ce7aa/out/chtype_size.c:6:10: fatal error: ncurses.h: No such file or directory
 #include <ncurses.h>
          ^~~~~~~~~~~
compilation terminated.
thread 'main' panicked at 'assertion failed: command.status().expect("compilation failed").success()', /home/ben/.cargo/registry/src/github.com-1ecc6299db9ec823/ncurses-5.99.0/build.rs:105:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

warning: build failed, waiting for other jobs to finish...
error: build failed

I'm sure the issue is just that I need to install ncurses globally or something, but I don't see this documented anywhere in the repo.

heap-use-after-free in auth_token_zero_on_drop test

https://asan.saethlin.dev/ub?crate=saltyrtc-client&version=0.9.0

test crypto_types::tests::auth_token_zero_on_drop ... =================================================================
==12103==ERROR: AddressSanitizer: heap-use-after-free on address 0x503000002320 at pc 0x5626b29754fb bp 0x7f04fe3f23d0 sp 0x7f04fe3f23c8
READ of size 1 at 0x503000002320 thread T9
    #0 0x5626b29754fa in core::fmt::num::imp::_$LT$impl$u20$core..fmt..Display$u20$for$u20$u8$GT$::fmt::h87ce992c3aaa24cf /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/num.rs:284:38
    #1 0x5626b28f582d in core::fmt::num::_$LT$impl$u20$core..fmt..Debug$u20$for$u20$u8$GT$::fmt::ha10a05c672d3d8ec /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/num.rs:195:21
    #2 0x5626b29c4f78 in _$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$::fmt::hb8ab0080a6c01fb6 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:2291:62
    #3 0x5626b29a5f3e in core::fmt::builders::DebugInner::entry::_$u7b$$u7b$closure$u7d$$u7d$::h4bea7e4618669186 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/builders.rs:403:17
    #4 0x5626b298e566 in core::result::Result$LT$T$C$E$GT$::and_then::h1b0f3bf0c0dd9a17 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:1320:22
    #5 0x5626b29a5ae5 in core::fmt::builders::DebugInner::entry::hd36ca6a72e7f640c /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/builders.rs:389:23
    #6 0x5626b29a65f9 in core::fmt::builders::DebugList::entry::h7563d9e7e73ad2e7 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/builders.rs:608:9
    #7 0x5626b29a786b in core::fmt::builders::DebugList::entries::hdaed61b6f09f28e6 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/builders.rs:642:13
    #8 0x5626b29c281b in _$LT$$u5b$T$u5d$$u20$as$u20$core..fmt..Debug$GT$::fmt::hb7bb2db0a31a7301 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:2519:9
    #9 0x5626b126a752 in generic_array::impls::_$LT$impl$u20$core..fmt..Debug$u20$for$u20$generic_array..GenericArray$LT$T$C$N$GT$$GT$::fmt::h65b9c904d1aa9b2e /root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/generic-array-0.14.7/src/impls.rs:70:9
    #10 0x5626b126b0e8 in _$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$::fmt::h9c7fb76587527613 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:2291:62
    #11 0x5626b29b83d1 in core::fmt::rt::Argument::fmt::h2d5da4a672b4c0a2 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/rt.rs:142:9
    #12 0x5626b29b83d1 in core::fmt::write::hd41a4cffff824c1e /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:1117:17
    #13 0x5626b265fe36 in std::io::Write::write_fmt::h4f2205ef49028bbb /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/mod.rs:1762:15
    #14 0x5626b2490344 in std::io::stdio::print_to_buffer_if_capture_used::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h855d93f65c3d2de1 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1032:25
    #15 0x5626b235c3f0 in core::option::Option$LT$T$GT$::map::hf551e015fa0aa3b9 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1065:29
    #16 0x5626b248fe26 in std::io::stdio::print_to_buffer_if_capture_used::_$u7b$$u7b$closure$u7d$$u7d$::h1a978b83b7d2bffd /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1031:13
    #17 0x5626b2433801 in std::thread::local::LocalKey$LT$T$GT$::try_with::h60a79e9a99f1297b /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:270:16
    #18 0x5626b248fbe0 in std::io::stdio::print_to_buffer_if_capture_used::hd45f5e447a4f3879 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1027:12
    #19 0x5626b248f3ab in std::io::stdio::print_to::hb2d74c8c8f81a7cc /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1015:8
    #20 0x5626b24906ff in std::io::stdio::_print::h026a3591ff197d15 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1097:5
    #21 0x5626b13b355d in saltyrtc_client::crypto_types::tests::auth_token_zero_on_drop::ha02e9743ef2c0e77 /build/src/crypto_types.rs:607:9
    #22 0x5626b13b1ff2 in saltyrtc_client::crypto_types::tests::auth_token_zero_on_drop::_$u7b$$u7b$closure$u7d$$u7d$::h4e07d0a4b00ebc09 /build/src/crypto_types.rs:577:33
0x503000002320 is located 0 bytes inside of 32-byte region [0x503000002320,0x503000002340)
freed by thread T9 here:
    #0 0x5626b1034486 in free /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3
    #1 0x5626b2560e81 in std::sys::unix::alloc::_$LT$impl$u20$core..alloc..global..GlobalAlloc$u20$for$u20$std..alloc..System$GT$::dealloc::h8a70c9434083b1d7 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/unix/alloc.rs:42:9
    #2 0x5626b1192a41 in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::deallocate::h7a016f1f2b16e119 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:254:22
    #3 0x5626b1215fa1 in _$LT$alloc..boxed..Box$LT$T$C$A$GT$$u20$as$u20$core..ops..drop..Drop$GT$::drop::h515205ed5db289a3 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:1235:17
    #4 0x5626b1390cc8 in core::ptr::drop_in_place$LT$alloc..boxed..Box$LT$saltyrtc_client..crypto_types..AuthToken$GT$$GT$::h6128f4ce55608063 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:498:1
    #5 0x5626b126c3f6 in core::mem::drop::hdf3f58d42dd972f2 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/mod.rs:987:24
    #6 0x5626b13b3120 in saltyrtc_client::crypto_types::tests::auth_token_zero_on_drop::ha02e9743ef2c0e77 /build/src/crypto_types.rs:602:9
    #7 0x5626b13b1ff2 in saltyrtc_client::crypto_types::tests::auth_token_zero_on_drop::_$u7b$$u7b$closure$u7d$$u7d$::h4e07d0a4b00ebc09 /build/src/crypto_types.rs:577:33
previously allocated by thread T9 here:
    #0 0x5626b103472e in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x5626b2560b7e in std::sys::unix::alloc::_$LT$impl$u20$core..alloc..global..GlobalAlloc$u20$for$u20$std..alloc..System$GT$::alloc::hbfc48fea06eea223 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/unix/alloc.rs:14:13
    #2 0x5626b24e152a in __rdl_alloc /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/alloc.rs:394:13
    #3 0x5626b11895b2 in alloc::alloc::Global::alloc_impl::h5f12886db83b3ae9 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:181:73
    #4 0x5626b1192aa7 in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::hfcdc6d972033eb10 /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:241:9
    #5 0x5626b13b24c7 in alloc::boxed::Box$LT$T$GT$::new::hf113b08cbf40200b /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:217:9
    #6 0x5626b13b24c7 in saltyrtc_client::crypto_types::tests::auth_token_zero_on_drop::ha02e9743ef2c0e77 /build/src/crypto_types.rs:581:21
    #7 0x5626b13b1ff2 in saltyrtc_client::crypto_types::tests::auth_token_zero_on_drop::_$u7b$$u7b$closure$u7d$$u7d$::h4e07d0a4b00ebc09 /build/src/crypto_types.rs:577:33
SUMMARY: AddressSanitizer: heap-use-after-free /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/num.rs:284:38 in core::fmt::num::imp::_$LT$impl$u20$core..fmt..Display$u20$for$u20$u8$GT$::fmt::h87ce992c3aaa24cf
Shadow bytes around the buggy address:
  0x503000002080: fd fd fd fd fa fa fd fd fd fd fa fa fd fd fd fd
  0x503000002100: fa fa fd fd fd fd fa fa fd fd fd fd fa fa fd fd
  0x503000002180: fd fd fa fa fd fd fd fd fa fa fd fd fd fd fa fa
  0x503000002200: fd fd fd fd fa fa 00 00 00 00 fa fa fd fd fd fd
  0x503000002280: fa fa fd fd fd fd fa fa 00 00 00 00 fa fa fd fd
=>0x503000002300: fd fd fa fa[fd]fd fd fd fa fa fd fd fd fa fa fa
  0x503000002380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x503000002400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x503000002480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x503000002500: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x503000002580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==12103==ABORTING

NoSharedTask: Send close message

When no shared task could be found, send a 'close' message to the peer.

Also check whether there are other places where we need to send the 'close' message.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.