Index: base/file_descriptor_shuffle.cc |
diff --git a/base/file_descriptor_shuffle.cc b/base/file_descriptor_shuffle.cc |
index e722a29e89fc5f3f0b646fbbef4188550ae68c51..2bb156bf3c7d5005cd55242744f6e5e0d5f0e38e 100644 |
--- a/base/file_descriptor_shuffle.cc |
+++ b/base/file_descriptor_shuffle.cc |
@@ -12,28 +12,36 @@ |
namespace base { |
-bool PerformInjectiveMultimap(const InjectiveMultimap& m_in, |
- InjectionDelegate* delegate) { |
- InjectiveMultimap m(m_in); |
- std::vector<int> extra_fds; |
+bool PerformInjectiveMultimapDestructive( |
+ InjectiveMultimap* m, InjectionDelegate* delegate) { |
+ static const size_t kMaxExtraFDs = 16; |
+ int extra_fds[kMaxExtraFDs]; |
+ unsigned next_extra_fd = 0; |
- for (InjectiveMultimap::iterator i = m.begin(); i != m.end(); ++i) { |
+ // DANGER: this function may not allocate. |
+ |
+ for (InjectiveMultimap::iterator i = m->begin(); i != m->end(); ++i) { |
int temp_fd = -1; |
// We DCHECK the injectiveness of the mapping. |
- for (InjectiveMultimap::iterator j = i + 1; j != m.end(); ++j) { |
+ for (InjectiveMultimap::iterator j = i + 1; j != m->end(); ++j) { |
DCHECK(i->dest != j->dest) << "Both fd " << i->source |
<< " and " << j->source << " map to " << i->dest; |
} |
const bool is_identity = i->source == i->dest; |
- for (InjectiveMultimap::iterator j = i + 1; j != m.end(); ++j) { |
+ for (InjectiveMultimap::iterator j = i + 1; j != m->end(); ++j) { |
if (!is_identity && i->dest == j->source) { |
if (temp_fd == -1) { |
if (!delegate->Duplicate(&temp_fd, i->dest)) |
return false; |
- extra_fds.push_back(temp_fd); |
+ if (next_extra_fd < kMaxExtraFDs) { |
+ extra_fds[next_extra_fd++] = temp_fd; |
+ } else { |
+ RAW_LOG(ERROR, "PerformInjectiveMultimapDestructive overflowed " |
+ "extra_fds. Leaking file descriptors!"); |
+ } |
} |
j->source = temp_fd; |
@@ -58,14 +66,18 @@ bool PerformInjectiveMultimap(const InjectiveMultimap& m_in, |
delegate->Close(i->source); |
} |
- for (std::vector<int>::const_iterator |
- i = extra_fds.begin(); i != extra_fds.end(); ++i) { |
- delegate->Close(*i); |
- } |
+ for (unsigned i = 0; i < next_extra_fd; i++) |
+ delegate->Close(extra_fds[i]); |
return true; |
} |
+bool PerformInjectiveMultimap(const InjectiveMultimap& m_in, |
+ InjectionDelegate* delegate) { |
+ InjectiveMultimap m(m_in); |
+ return PerformInjectiveMultimapDestructive(&m, delegate); |
+} |
+ |
bool FileDescriptorTableInjection::Duplicate(int* result, int fd) { |
*result = HANDLE_EINTR(dup(fd)); |
return *result >= 0; |