[v8/el6: 1/2] nodejs 0.10.31/0.10.32 backport roundup
T.C. Hollingsworth
patches at fedoraproject.org
Thu Sep 18 02:37:48 UTC 2014
commit 643e7db07d4b0d35d30650c025e1a0a99e7564f1
Author: T.C. Hollingsworth <tchollingsworth at gmail.com>
Date: Wed Sep 17 19:35:04 2014 -0700
nodejs 0.10.31/0.10.32 backport roundup
- backport bugfix that eliminates unused-local-typedefs warning
- backport security fix: Fix Hydrogen bounds check elimination (CVE-2013-6668; RHBZ#1086120)
- backport fix to segfault caused by the above patch
v8-3.14.5.10-CVE-2013-6668-segfault.patch | 60 ++++++++
v8-3.14.5.10-CVE-2013-6668.patch | 186 ++++++++++++++++++++++++++
v8-3.14.5.10-interrupts-stack-overflow.patch | 31 +++++
v8-3.14.5.10-unused-local-typedefs.patch | 39 ++++++
v8.spec | 24 +++-
5 files changed, 339 insertions(+), 1 deletions(-)
---
diff --git a/v8-3.14.5.10-CVE-2013-6668-segfault.patch b/v8-3.14.5.10-CVE-2013-6668-segfault.patch
new file mode 100644
index 0000000..8e3d600
--- /dev/null
+++ b/v8-3.14.5.10-CVE-2013-6668-segfault.patch
@@ -0,0 +1,60 @@
+From 3122e0eae64c5ab494b29d0a9cadef902d93f1f9 Mon Sep 17 00:00:00 2001
+From: Fedor Indutny <fedor at indutny.com>
+Date: Fri, 22 Aug 2014 03:59:35 +0400
+Subject: [PATCH] deps: fix up v8 after fd80a3
+
+fd80a31e0697d6317ce8c2d289575399f4e06d21 has introduced a segfault
+during redundant boundary check elimination (#8208).
+
+The problem consists of two parts:
+
+ 1. Abscense of instruction iterator in
+ `EliminateRedundantBoundsChecks`. It was present in recent v8, but
+ wasn't considered important at the time of backport. However, since
+ the function is changing instructions order in block, it is
+ important to not rely at `i->next()` at the end of the loop.
+ 2. Too strict ASSERT in `MoveIndexIfNecessary`. It is essentially a
+ backport of a45c96ab from v8's upstream. See
+ https://github.com/v8/v8/commit/a45c96ab for details.
+
+fix #8208
+---
+ src/hydrogen.cc | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/src/hydrogen.cc b/src/hydrogen.cc
+index 50d8e49..18a6b60 100644
+--- a/src/hydrogen.cc
++++ b/src/hydrogen.cc
+@@ -3546,7 +3546,11 @@ class BoundsCheckBbData: public ZoneObject {
+ void MoveIndexIfNecessary(HValue* index_raw,
+ HBoundsCheck* insert_before,
+ HInstruction* end_of_scan_range) {
+- ASSERT(index_raw->IsAdd() || index_raw->IsSub());
++ if (!index_raw->IsAdd() && !index_raw->IsSub()) {
++ // index_raw can be HAdd(index_base, offset), HSub(index_base, offset),
++ // or index_base directly. In the latter case, no need to move anything.
++ return;
++ }
+ HBinaryOperation* index =
+ HArithmeticBinaryOperation::cast(index_raw);
+ HValue* left_input = index->left();
+@@ -3581,7 +3585,6 @@ class BoundsCheckBbData: public ZoneObject {
+ HBoundsCheck* tighter_check) {
+ ASSERT(original_check->length() == tighter_check->length());
+ MoveIndexIfNecessary(tighter_check->index(), original_check, tighter_check);
+- original_check->ReplaceAllUsesWith(original_check->index());
+ original_check->SetOperandAt(0, tighter_check->index());
+ }
+ };
+@@ -3624,7 +3627,9 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
+ BoundsCheckTable* table) {
+ BoundsCheckBbData* bb_data_list = NULL;
+
+- for (HInstruction* i = bb->first(); i != NULL; i = i->next()) {
++ HInstruction* next;
++ for (HInstruction* i = bb->first(); i != NULL; i = next) {
++ next = i->next();
+ if (!i->IsBoundsCheck()) continue;
+
+ HBoundsCheck* check = HBoundsCheck::cast(i);
diff --git a/v8-3.14.5.10-CVE-2013-6668.patch b/v8-3.14.5.10-CVE-2013-6668.patch
new file mode 100644
index 0000000..fe5cb6d
--- /dev/null
+++ b/v8-3.14.5.10-CVE-2013-6668.patch
@@ -0,0 +1,186 @@
+From fd80a31e0697d6317ce8c2d289575399f4e06d21 Mon Sep 17 00:00:00 2001
+From: Fedor Indutny <fedor at indutny.com>
+Date: Thu, 14 Aug 2014 19:29:28 +0400
+Subject: [PATCH] deps: backport 5f836c from v8 upstream
+
+Original commit message:
+
+ Fix Hydrogen bounds check elimination
+
+ When combining bounds checks, they must all be moved before the first load/store
+ that they are guarding.
+
+ BUG=chromium:344186
+ LOG=y
+ R=svenpanne at chromium.org
+
+ Review URL: https://codereview.chromium.org/172093002
+
+ git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@19475 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
+
+fix #8070
+---
+ src/hydrogen.cc | 106 +++++++++++++++++++++++-------------------------
+ 1 file changed, 50 insertions(+), 56 deletions(-)
+
+diff --git a/src/hydrogen.cc b/src/hydrogen.cc
+index e3f79ee..50d8e49 100644
+--- a/src/hydrogen.cc
++++ b/src/hydrogen.cc
+@@ -3487,13 +3487,7 @@ class BoundsCheckBbData: public ZoneObject {
+ keep_new_check = true;
+ upper_check_ = new_check;
+ } else {
+- BuildOffsetAdd(upper_check_,
+- &added_upper_index_,
+- &added_upper_offset_,
+- Key()->IndexBase(),
+- new_check->index()->representation(),
+- new_offset);
+- upper_check_->SetOperandAt(0, added_upper_index_);
++ TightenCheck(upper_check_, new_check);
+ }
+ } else if (new_offset < lower_offset_) {
+ lower_offset_ = new_offset;
+@@ -3501,28 +3495,27 @@ class BoundsCheckBbData: public ZoneObject {
+ keep_new_check = true;
+ lower_check_ = new_check;
+ } else {
+- BuildOffsetAdd(lower_check_,
+- &added_lower_index_,
+- &added_lower_offset_,
+- Key()->IndexBase(),
+- new_check->index()->representation(),
+- new_offset);
+- lower_check_->SetOperandAt(0, added_lower_index_);
++ TightenCheck(lower_check_, new_check);
+ }
+ } else {
+- ASSERT(false);
++ // Should never have called CoverCheck() in this case.
++ UNREACHABLE();
+ }
+
+ if (!keep_new_check) {
+ new_check->DeleteAndReplaceWith(NULL);
++ } else {
++ HBoundsCheck* first_check = new_check == lower_check_ ? upper_check_
++ : lower_check_;
++ // The length is guaranteed to be live at first_check.
++ ASSERT(new_check->length() == first_check->length());
++ HInstruction* old_position = new_check->next();
++ new_check->Unlink();
++ new_check->InsertAfter(first_check);
++ MoveIndexIfNecessary(new_check->index(), new_check, old_position);
+ }
+ }
+
+- void RemoveZeroOperations() {
+- RemoveZeroAdd(&added_lower_index_, &added_lower_offset_);
+- RemoveZeroAdd(&added_upper_index_, &added_upper_offset_);
+- }
+-
+ BoundsCheckBbData(BoundsCheckKey* key,
+ int32_t lower_offset,
+ int32_t upper_offset,
+@@ -3537,10 +3530,6 @@ class BoundsCheckBbData: public ZoneObject {
+ basic_block_(bb),
+ lower_check_(lower_check),
+ upper_check_(upper_check),
+- added_lower_index_(NULL),
+- added_lower_offset_(NULL),
+- added_upper_index_(NULL),
+- added_upper_offset_(NULL),
+ next_in_bb_(next_in_bb),
+ father_in_dt_(father_in_dt) { }
+
+@@ -3551,44 +3540,50 @@ class BoundsCheckBbData: public ZoneObject {
+ HBasicBlock* basic_block_;
+ HBoundsCheck* lower_check_;
+ HBoundsCheck* upper_check_;
+- HAdd* added_lower_index_;
+- HConstant* added_lower_offset_;
+- HAdd* added_upper_index_;
+- HConstant* added_upper_offset_;
+ BoundsCheckBbData* next_in_bb_;
+ BoundsCheckBbData* father_in_dt_;
+
+- void BuildOffsetAdd(HBoundsCheck* check,
+- HAdd** add,
+- HConstant** constant,
+- HValue* original_value,
+- Representation representation,
+- int32_t new_offset) {
+- HConstant* new_constant = new(BasicBlock()->zone())
+- HConstant(new_offset, Representation::Integer32());
+- if (*add == NULL) {
+- new_constant->InsertBefore(check);
+- // Because of the bounds checks elimination algorithm, the index is always
+- // an HAdd or an HSub here, so we can safely cast to an HBinaryOperation.
+- HValue* context = HBinaryOperation::cast(check->index())->context();
+- *add = new(BasicBlock()->zone()) HAdd(context,
+- original_value,
+- new_constant);
+- (*add)->AssumeRepresentation(representation);
+- (*add)->InsertBefore(check);
+- } else {
+- new_constant->InsertBefore(*add);
+- (*constant)->DeleteAndReplaceWith(new_constant);
++ void MoveIndexIfNecessary(HValue* index_raw,
++ HBoundsCheck* insert_before,
++ HInstruction* end_of_scan_range) {
++ ASSERT(index_raw->IsAdd() || index_raw->IsSub());
++ HBinaryOperation* index =
++ HArithmeticBinaryOperation::cast(index_raw);
++ HValue* left_input = index->left();
++ HValue* right_input = index->right();
++ bool must_move_index = false;
++ bool must_move_left_input = false;
++ bool must_move_right_input = false;
++ for (HInstruction* cursor = end_of_scan_range; cursor != insert_before;) {
++ if (cursor == left_input) must_move_left_input = true;
++ if (cursor == right_input) must_move_right_input = true;
++ if (cursor == index) must_move_index = true;
++ if (cursor->previous() == NULL) {
++ cursor = cursor->block()->dominator()->end();
++ } else {
++ cursor = cursor->previous();
++ }
+ }
+- *constant = new_constant;
+- }
+
+- void RemoveZeroAdd(HAdd** add, HConstant** constant) {
+- if (*add != NULL && (*constant)->Integer32Value() == 0) {
+- (*add)->DeleteAndReplaceWith((*add)->left());
+- (*constant)->DeleteAndReplaceWith(NULL);
++ // The BCE algorithm only selects mergeable bounds checks that share
++ // the same "index_base", so we'll only ever have to move constants.
++ if (must_move_left_input) {
++ HConstant::cast(left_input)->Unlink();
++ HConstant::cast(left_input)->InsertBefore(index);
++ }
++ if (must_move_right_input) {
++ HConstant::cast(right_input)->Unlink();
++ HConstant::cast(right_input)->InsertBefore(index);
+ }
+ }
++
++ void TightenCheck(HBoundsCheck* original_check,
++ HBoundsCheck* tighter_check) {
++ ASSERT(original_check->length() == tighter_check->length());
++ MoveIndexIfNecessary(tighter_check->index(), original_check, tighter_check);
++ original_check->ReplaceAllUsesWith(original_check->index());
++ original_check->SetOperandAt(0, tighter_check->index());
++ }
+ };
+
+
+@@ -3683,7 +3678,6 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
+ for (BoundsCheckBbData* data = bb_data_list;
+ data != NULL;
+ data = data->NextInBasicBlock()) {
+- data->RemoveZeroOperations();
+ if (data->FatherInDominatorTree()) {
+ table->Insert(data->Key(), data->FatherInDominatorTree(), zone());
+ } else {
diff --git a/v8-3.14.5.10-interrupts-stack-overflow.patch b/v8-3.14.5.10-interrupts-stack-overflow.patch
new file mode 100644
index 0000000..049b4df
--- /dev/null
+++ b/v8-3.14.5.10-interrupts-stack-overflow.patch
@@ -0,0 +1,31 @@
+From 530af9cb8e700e7596b3ec812bad123c9fa06356 Mon Sep 17 00:00:00 2001
+From: Fedor Indutny <fedor at indutny.com>
+Date: Wed, 30 Jul 2014 15:33:52 -0700
+Subject: [PATCH] v8: Interrupts must not mask stack overflow.
+
+Backport of https://codereview.chromium.org/339883002
+---
+ src/isolate.h | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/src/isolate.h b/src/isolate.h
+index b90191d..2769ca7 100644
+--- a/src/isolate.h
++++ b/src/isolate.h
+@@ -1392,14 +1392,9 @@ class StackLimitCheck BASE_EMBEDDED {
+ public:
+ explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { }
+
+- bool HasOverflowed() const {
++ inline bool HasOverflowed() const {
+ StackGuard* stack_guard = isolate_->stack_guard();
+- // Stack has overflowed in C++ code only if stack pointer exceeds the C++
+- // stack guard and the limits are not set to interrupt values.
+- // TODO(214): Stack overflows are ignored if a interrupt is pending. This
+- // code should probably always use the initial C++ limit.
+- return (reinterpret_cast<uintptr_t>(this) < stack_guard->climit()) &&
+- stack_guard->IsStackOverflow();
++ return reinterpret_cast<uintptr_t>(this) < stack_guard->real_climit();
+ }
+ private:
+ Isolate* isolate_;
diff --git a/v8-3.14.5.10-unused-local-typedefs.patch b/v8-3.14.5.10-unused-local-typedefs.patch
new file mode 100644
index 0000000..c168875
--- /dev/null
+++ b/v8-3.14.5.10-unused-local-typedefs.patch
@@ -0,0 +1,39 @@
+From 53b4accb6e5747b156be91a2b90f42607e33a7cc Mon Sep 17 00:00:00 2001
+From: Timothy J Fontaine <tjfontaine at gmail.com>
+Date: Mon, 4 Aug 2014 13:43:50 -0700
+Subject: [PATCH] v8: Fix compliation with GCC 4.8
+
+Supresses a very loud warning from GCC 4.8 about unused typedefs
+
+Original url https://codereview.chromium.org/69413002
+---
+ src/checks.h | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/src/checks.h b/src/checks.h
+index d0a0c2b..4396ada 100644
+--- a/src/checks.h
++++ b/src/checks.h
+@@ -230,6 +230,13 @@ inline void CheckNonEqualsHelper(const char* file,
+ #define CHECK_LE(a, b) CHECK((a) <= (b))
+
+
++#if defined(__clang__) || defined(__GNUC__)
++# define V8_UNUSED __attribute__((unused))
++#else
++# define V8_UNUSED
++#endif
++
++
+ // This is inspired by the static assertion facility in boost. This
+ // is pretty magical. If it causes you trouble on a platform you may
+ // find a fix in the boost code.
+@@ -248,7 +255,7 @@ template <int> class StaticAssertionHelper { };
+ #define STATIC_CHECK(test) \
+ typedef \
+ StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \
+- SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
++ SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) V8_UNUSED
+
+
+ extern bool FLAG_enable_slow_asserts;
diff --git a/v8.spec b/v8.spec
index 83a36fb..ebbefd6 100644
--- a/v8.spec
+++ b/v8.spec
@@ -79,6 +79,20 @@ Patch9: v8-3.14.5.10-mem-corruption-stack-overflow.patch
# https://github.com/joyent/node/commit/3530fa9cd09f8db8101c4649cab03bcdf760c434
Patch10: v8-3.14.5.10-x64-MathMinMax.patch
+# backport bugfix that eliminates unused-local-typedefs warning
+# https://github.com/joyent/node/commit/53b4accb6e5747b156be91a2b90f42607e33a7cc
+Patch11: v8-3.14.5.10-unused-local-typedefs.patch
+
+# backport security fix: Fix Hydrogen bounds check elimination
+# resolves CVE-2013-6668 (RHBZ#1086120)
+# https://github.com/joyent/node/commit/fd80a31e0697d6317ce8c2d289575399f4e06d21
+Patch12: v8-3.14.5.10-CVE-2013-6668.patch
+
+# backport fix to segfault caused by the above patch
+# https://github.com/joyent/node/commit/3122e0eae64c5ab494b29d0a9cadef902d93f1f9
+Patch13: v8-3.14.5.10-CVE-2013-6668-segfault.patch
+
+
%description
V8 is Google's open source JavaScript engine. V8 is written in C++ and is used
in Google Chrome, the open source browser from Google. V8 implements ECMAScript
@@ -104,6 +118,9 @@ Development headers and libraries for v8.
%patch8 -p1
%patch9 -p1
%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
#Patch7 needs -lrt on glibc < 2.17 (RHEL <= 6)
%if (0%{?rhel} > 6 || 0%{?fedora} > 18)
@@ -113,7 +130,7 @@ Development headers and libraries for v8.
%endif
# -fno-strict-aliasing is needed with gcc 4.4 to get past some ugly code
-PARSED_OPT_FLAGS=`echo \'$RPM_OPT_FLAGS %{lrt} -fPIC -fno-strict-aliasing -Wno-unused-parameter -Wno-error=strict-overflow -Wno-error=unused-local-typedefs -Wno-unused-but-set-variable\'| sed "s/ /',/g" | sed "s/',/', '/g"`
+PARSED_OPT_FLAGS=`echo \'$RPM_OPT_FLAGS %{lrt} -fPIC -fno-strict-aliasing -Wno-unused-parameter -Wno-error=strict-overflow -Wno-unused-but-set-variable\'| sed "s/ /',/g" | sed "s/',/', '/g"`
sed -i "s|'-O3',|$PARSED_OPT_FLAGS,|g" SConstruct
# clear spurious executable bits
@@ -268,6 +285,11 @@ rm -rf %{buildroot}
%{python_sitelib}/j*.py*
%changelog
+* Wed Sep 17 2014 T.C. Hollingsworth <tchollingsworth at gmail.com> - 1:3.14.5.10-12
+- backport bugfix that eliminates unused-local-typedefs warning
+- backport security fix: Fix Hydrogen bounds check elimination (CVE-2013-6668; RHBZ#1086120)
+- backport fix to segfault caused by the above patch
+
* Thu Jul 31 2014 T.C. Hollingsworth <tchollingsworth at gmail.com> - 1:3.14.5.10-11
- backport security fix for memory corruption and stack overflow (RHBZ#1125464)
https://groups.google.com/d/msg/nodejs/-siJEObdp10/2xcqqmTHiEMJ
More information about the scm-commits
mailing list