|
|
2acdd5 |
|
|
|
2acdd5 |
# HG changeset patch
|
|
|
2acdd5 |
# User Jed Davis <jld@mozilla.com>
|
|
|
2acdd5 |
# Date 1526943705 21600
|
|
|
2acdd5 |
# Node ID 6bb3adfa15c6877f7874429462dad88f8c978c4f
|
|
|
2acdd5 |
# Parent 4c71c8454879c841871ecf3afb7dbdc96bad97fc
|
|
|
2acdd5 |
Bug 1436242 - Avoid undefined behavior in IPC fd-passing code. r=froydnj
|
|
|
2acdd5 |
|
|
|
2acdd5 |
MozReview-Commit-ID: 3szIPUssgF5
|
|
|
2acdd5 |
|
|
|
2acdd5 |
diff --git a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
|
|
|
2acdd5 |
--- a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
|
|
|
2acdd5 |
+++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
|
|
|
2acdd5 |
@@ -418,20 +418,37 @@ bool Channel::ChannelImpl::ProcessIncomi
|
|
|
2acdd5 |
const int* fds;
|
|
|
2acdd5 |
unsigned num_fds;
|
|
|
2acdd5 |
unsigned fds_i = 0; // the index of the first unused descriptor
|
|
|
2acdd5 |
|
|
|
2acdd5 |
if (input_overflow_fds_.empty()) {
|
|
|
2acdd5 |
fds = wire_fds;
|
|
|
2acdd5 |
num_fds = num_wire_fds;
|
|
|
2acdd5 |
} else {
|
|
|
2acdd5 |
- const size_t prev_size = input_overflow_fds_.size();
|
|
|
2acdd5 |
- input_overflow_fds_.resize(prev_size + num_wire_fds);
|
|
|
2acdd5 |
- memcpy(&input_overflow_fds_[prev_size], wire_fds,
|
|
|
2acdd5 |
- num_wire_fds * sizeof(int));
|
|
|
2acdd5 |
+ // This code may look like a no-op in the case where
|
|
|
2acdd5 |
+ // num_wire_fds == 0, but in fact:
|
|
|
2acdd5 |
+ //
|
|
|
2acdd5 |
+ // 1. wire_fds will be nullptr, so passing it to memcpy is
|
|
|
2acdd5 |
+ // undefined behavior according to the C standard, even though
|
|
|
2acdd5 |
+ // the memcpy length is 0.
|
|
|
2acdd5 |
+ //
|
|
|
2acdd5 |
+ // 2. prev_size will be an out-of-bounds index for
|
|
|
2acdd5 |
+ // input_overflow_fds_; this is undefined behavior according to
|
|
|
2acdd5 |
+ // the C++ standard, even though the element only has its
|
|
|
2acdd5 |
+ // pointer taken and isn't accessed (and the corresponding
|
|
|
2acdd5 |
+ // operation on a C array would be defined).
|
|
|
2acdd5 |
+ //
|
|
|
2acdd5 |
+ // UBSan makes #1 a fatal error, and assertions in libstdc++ do
|
|
|
2acdd5 |
+ // the same for #2 if enabled.
|
|
|
2acdd5 |
+ if (num_wire_fds > 0) {
|
|
|
2acdd5 |
+ const size_t prev_size = input_overflow_fds_.size();
|
|
|
2acdd5 |
+ input_overflow_fds_.resize(prev_size + num_wire_fds);
|
|
|
2acdd5 |
+ memcpy(&input_overflow_fds_[prev_size], wire_fds,
|
|
|
2acdd5 |
+ num_wire_fds * sizeof(int));
|
|
|
2acdd5 |
+ }
|
|
|
2acdd5 |
fds = &input_overflow_fds_[0];
|
|
|
2acdd5 |
num_fds = input_overflow_fds_.size();
|
|
|
2acdd5 |
}
|
|
|
2acdd5 |
|
|
|
2acdd5 |
// The data for the message we're currently reading consists of any data
|
|
|
2acdd5 |
// stored in incoming_message_ followed by data in input_buf_ (followed by
|
|
|
2acdd5 |
// other messages).
|
|
|
2acdd5 |
|
|
|
2acdd5 |
|