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

fix race condition in iOS websocket implementation #32847

Closed
wants to merge 1 commit into from

Conversation

asmeikal
Copy link
Contributor

@asmeikal asmeikal commented Jan 7, 2022

Summary

The iOS WebSocket implementation has a race condition that causes WebSocket frame payloads to be processed incorrectly.
This can cause errors on RFC6455 compliant WebSocket servers:

  • the server sends a ping frame with no payload
  • the server sends a text frame with a payload longer than 125 bytes
  • the client answers the ping with a pong frame echoing back the contents of the text frame

This is caused by concurrent modification of the current frame contents, that is passed by reference to the handlers. The concurrent modification happens here.

The bug was detected and fixed in the original SocketRocket repository in this PR. The relevant part of the fix is applied in this PR.

Resolves #30020.

Changelog

[iOS] [Fixed] - Fix WebSocket control frames having payloads longer than 125 bytes

Test Plan

The bug is not easily and consistently reproduced, being a race condition.
We were able to reproduce it by connecting a react native app to a websocket server that sent ~100 pings per second and ~100 text frames per second. After a couple of seconds, the server receives an invalid pong message, with a payload equal to the payload of the text frame. The following is a node server that can replicate the problem on a react-native app running on iOS.

const { WebSocketServer } = require('ws');

const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', function connection(ws) {
  const pingInterval = setInterval(() => {
    ws.ping();
  }, 10);

  const sendInterval = setInterval(() => {
    const arr = new Array(100);
    for (let i = 0; i < arr.length; i++) {
      arr[i] = Math.random();
    }
    ws.send('message with payload longer than 125 bytes: ' + arr.join(','));
  }, 10);

  ws.on('close', () => {
    clearInterval(pingInterval);
    clearInterval(sendInterval);
  });

  ws.on('error', (err) => {
    console.error(err);
    process.exit(1);
  });
});

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Jan 7, 2022
@react-native-bot react-native-bot added Bug Platform: iOS iOS applications. labels Jan 7, 2022
@analysis-bot
Copy link

Platform Engine Arch Size (bytes) Diff
ios - universal n/a --

Base commit: ca5aaa7
Branch: main

@analysis-bot
Copy link

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 8,289,885 +0
android hermes armeabi-v7a 7,624,822 +0
android hermes x86 8,762,300 +0
android hermes x86_64 8,699,301 +0
android jsc arm64-v8a 9,678,193 +0
android jsc armeabi-v7a 8,669,807 +0
android jsc x86 9,636,108 +0
android jsc x86_64 10,230,705 +0

Base commit: ca5aaa7
Branch: main

@facebook-github-bot
Copy link
Contributor

@sota000 has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@react-native-bot
Copy link
Collaborator

This pull request was successfully merged by @asmeikal in 86db62b.

When will my fix make it into a release? | Upcoming Releases

@react-native-bot react-native-bot added the Merged This PR has been merged. label Jan 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. Platform: iOS iOS applications. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Websocket Wrong Control Frame [iOS]
4 participants