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

v4.8.3 proposal #12499

Merged
merged 15 commits into from
May 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 65 additions & 5 deletions BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,76 @@ If you consistently can reproduce a test failure, search for it in the
[Node.js issue tracker](https://github.com/nodejs/node/issues) or
file a new issue.

## Supported platforms

This list of supported platforms is current as of the branch / release to
which it is attached.

### Input

Node.js relies on V8 and libuv. Therefore, we adopt a subset of their
supported platforms.

### Strategy

Support is divided into three tiers:

* **Tier 1**: Full test coverage and maintenance by the Node.js core team and
the broader community.
* **Tier 2**: Full test coverage but more limited maintenance,
often provided by the vendor of the platform.
* **Experimental**: Known to compile but not necessarily reliably or with
a full passing test suite. These are often working to be promoted to Tier
2 but are not quite ready. There is at least one individual actively
providing maintenance and the team is striving to broaden quality and
reliability of support.

### Supported platforms

| System | Support type | Version | Architectures | Notes |
|--------------|--------------|----------------------------------|----------------------|------------------|
| GNU/Linux | Tier 1 | kernel >= 2.6.18, glibc >= 2.5 | x86, x64, arm, arm64 | |
| macOS | Tier 1 | >= 10.10 | x64 | |
| Windows | Tier 1 | >= Windows 7 or >= Windows2008R2 | x86, x64 | |
| SmartOS | Tier 2 | >= 14 | x86, x64 | |
| FreeBSD | Tier 2 | >= 10 | x64 | |
| GNU/Linux | Tier 2 | kernel >= 4.2.0, glibc >= 2.19 | ppc64be | |
| GNU/Linux | Tier 2 | kernel >= 3.13.0, glibc >= 2.19 | ppc64le | |
| macOS | Experimental | >= 10.8 < 10.10 | x64 | no test coverage |
| Linux (musl) | Experimental | musl >= 1.0 | x64 | |


### Supported toolchains

Depending on host platform, the selection of toolchains may vary.

#### Unix

* GCC 4.8 or newer
* Clang 3.4.1 or newer

#### Windows

* Building Node: Visual Studio 2013 or Visual C++ Build Tools 2013 or newer
* Building native add-ons: Visual Studio 2013 or Visual C++ Build Tools 2013
or newer

## Building Node.js on supported platforms

### Unix / OS X

Prerequisites:

* `gcc` and `g++` 4.8 or newer, or
* `clang` and `clang++` 3.4 or newer
* `clang` and `clang++` 3.4.1 or newer
* Python 2.6 or 2.7
* GNU Make 3.81 or newer

On OS X, you will also need:
* [Xcode](https://developer.apple.com/xcode/download/)
* You also need to install the `Command Line Tools` via Xcode. You can find
- You also need to install the `Command Line Tools` via Xcode. You can find
this under the menu `Xcode -> Preferences -> Downloads`
* This step will install `gcc` and the related toolchain containing `make`
- This step will install `gcc` and the related toolchain containing `make`

* After building, you may want to setup [firewall rules](tools/macosx-firewall.sh)
to avoid popups asking to accept incoming network connections when running tests:
Expand Down Expand Up @@ -53,6 +108,9 @@ $ make
$ [sudo] make install
```

Note that the above requires that `python` resolve to Python 2.6 or 2.7
and not a newer version.

To run the tests:

```text
Expand Down Expand Up @@ -263,9 +321,11 @@ It is possible to build Node.js with

**Note**: building in this way does **not** allow you to claim that the
runtime is FIPS 140-2 validated. Instead you can indicate that the runtime
uses a validated module. See the [security policy](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf)
uses a validated module. See the
[security policy](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf)
page 60 for more details. In addition, the validation for the underlying module
is only valid if it is deployed in accordance with its [security policy](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf).
is only valid if it is deployed in accordance with its
[security policy](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf).
If you need FIPS validated cryptography it is recommended that you read both
the [security policy](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf)
and [user guide](https://openssl.org/docs/fips/UserGuide-2.0.pdf).
Expand Down
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Node.js ChangeLog

## 2017-05-02, Version 4.8.3 'Argon' (Maintenance), @MylesBorins

### Notable Changes

* **module**:
- The [module loading global fallback](https://nodejs.org/dist/latest-v4.x/docs/api/modules.html#modules_loading_from_the_global_folders) to the Node executable's directory now works correctly on Windows. (Richard Lau) [#9283](https://github.com/nodejs/node/pull/9283)
* **src**:
- fix base64 decoding in rare edgecase (Nikolai Vavilov) [#11995](https://github.com/nodejs/node/pull/11995)
* **tls**:
- fix rare segmentation faults when using TLS
* (Trevor Norris) [#11947](https://github.com/nodejs/node/pull/11947)
* (Ben Noordhuis) [#11898](https://github.com/nodejs/node/pull/11898)
* (jBarz) [#11776](https://github.com/nodejs/node/pull/11776)

### Commits

* [[`44260806a6`](https://github.com/nodejs/node/commit/44260806a6)] - Partial revert "tls: keep track of stream that is closed" (Trevor Norris) [#11947](https://github.com/nodejs/node/pull/11947)
* [[`ab3fdf531f`](https://github.com/nodejs/node/commit/ab3fdf531f)] - **deps**: cherry-pick ca0f9573 from V8 upstream (Ali Ijaz Sheikh) [#11940](https://github.com/nodejs/node/pull/11940)
* [[`07b92a3c0b`](https://github.com/nodejs/node/commit/07b92a3c0b)] - **doc**: add supported platforms list for v4.x (Michael Dawson) [#12091](https://github.com/nodejs/node/pull/12091)
* [[`ba91c41478`](https://github.com/nodejs/node/commit/ba91c41478)] - **module**: fix loading from global folders on Windows (Richard Lau) [#9283](https://github.com/nodejs/node/pull/9283)
* [[`b5b78b12b8`](https://github.com/nodejs/node/commit/b5b78b12b8)] - **src**: add fcntl.h include to node.cc (Bartosz Sosnowski) [#12540](https://github.com/nodejs/node/pull/12540)
* [[`eb393f9ae1`](https://github.com/nodejs/node/commit/eb393f9ae1)] - **src**: fix base64 decoding (Nikolai Vavilov) [#11995](https://github.com/nodejs/node/pull/11995)
* [[`8ed18a1429`](https://github.com/nodejs/node/commit/8ed18a1429)] - **src**: ensure that fd 0-2 are valid on windows (Bartosz Sosnowski) [#11863](https://github.com/nodejs/node/pull/11863)
* [[`ff1d61c11b`](https://github.com/nodejs/node/commit/ff1d61c11b)] - **stream_base,tls_wrap**: notify on destruct (Trevor Norris) [#11947](https://github.com/nodejs/node/pull/11947)
* [[`6040efd7dc`](https://github.com/nodejs/node/commit/6040efd7dc)] - **test**: fix flaky test-tls-wrap-timeout (Rich Trott) [#7857](https://github.com/nodejs/node/pull/7857)
* [[`7a1920dc84`](https://github.com/nodejs/node/commit/7a1920dc84)] - **test**: add hasCrypto check to tls-socket-close (Daniel Bevenius) [#11911](https://github.com/nodejs/node/pull/11911)
* [[`1dc6b38dcf`](https://github.com/nodejs/node/commit/1dc6b38dcf)] - **test**: add test for loading from global folders (Richard Lau) [#9283](https://github.com/nodejs/node/pull/9283)
* [[`54f5258582`](https://github.com/nodejs/node/commit/54f5258582)] - **tls**: fix segfault on destroy after partial read (Ben Noordhuis) [#11898](https://github.com/nodejs/node/pull/11898)
* [[`99749dccfe`](https://github.com/nodejs/node/commit/99749dccfe)] - **tls**: keep track of stream that is closed (jBarz) [#11776](https://github.com/nodejs/node/pull/11776)
* [[`6d3aaa72a8`](https://github.com/nodejs/node/commit/6d3aaa72a8)] - **tls**: TLSSocket emits 'error' on handshake failure (Mariusz 'koder' Chwalba) [#8805](https://github.com/nodejs/node/pull/8805)

## 2017-04-04, Version 4.8.2 'Argon' (Maintenance), @MylesBorins

This is a maintenance release to fix a memory leak that was introduced in 4.8.1.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ the binary verification command above.
## Building Node.js

See [BUILDING.md](BUILDING.md) for instructions on how to build
Node.js from source.
Node.js from source along with a list of officially supported platforms.

## Security

Expand Down
2 changes: 1 addition & 1 deletion deps/v8/include/v8-version.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 4
#define V8_MINOR_VERSION 5
#define V8_BUILD_NUMBER 103
#define V8_PATCH_LEVEL 46
#define V8_PATCH_LEVEL 47

// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
Expand Down
14 changes: 11 additions & 3 deletions deps/v8/src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6580,7 +6580,11 @@ Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
ENTER_V8(i_isolate);
i::Handle<i::JSArrayBuffer> obj =
i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared);
i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length);
// TODO(jbroman): It may be useful in the future to provide a MaybeLocal
// version that throws an exception or otherwise does not crash.
if (!i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length)) {
i::FatalProcessOutOfMemory("v8::ArrayBuffer::New");
}
return Utils::ToLocal(obj);
}

Expand Down Expand Up @@ -6775,8 +6779,12 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate,
ENTER_V8(i_isolate);
i::Handle<i::JSArrayBuffer> obj =
i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length, true,
i::SharedFlag::kShared);
// TODO(jborman): It may be useful in the future to provide a MaybeLocal
// version that throws an exception or otherwise does not crash.
if (!i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length, true,
i::SharedFlag::kShared)) {
i::FatalProcessOutOfMemory("v8::SharedArrayBuffer::New");
}
return Utils::ToLocalShared(obj);
}

Expand Down
4 changes: 3 additions & 1 deletion lib/_tls_wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,9 @@ TLSSocket.prototype._init = function(socket, wrap) {

// Destroy socket if error happened before handshake's finish
if (!self._secureEstablished) {
self.destroy(self._tlsError(err));
// When handshake fails control is not yet released,
// so self._tlsError will return null instead of actual error
self.destroy(err);
} else if (options.isServer &&
rejectUnauthorized &&
/peer did not return a certificate/.test(err.message)) {
Expand Down
11 changes: 10 additions & 1 deletion lib/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,16 @@ Module._initPaths = function() {
homeDir = process.env.HOME;
}

var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')];
// $PREFIX/lib/node, where $PREFIX is the root of the Node.js installation.
var prefixDir;
// process.execPath is $PREFIX/bin/node except on Windows where it is
// $PREFIX\node.exe.
if (isWindows) {
prefixDir = path.resolve(process.execPath, '..');
} else {
prefixDir = path.resolve(process.execPath, '..', '..');
}
var paths = [path.resolve(prefixDir, 'lib', 'node')];

if (homeDir) {
paths.unshift(path.resolve(homeDir, '.node_libraries'));
Expand Down
14 changes: 14 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#endif

#include <errno.h>
#include <fcntl.h> // _O_RDWR
#include <limits.h> // PATH_MAX
#include <locale.h>
#include <signal.h>
Expand Down Expand Up @@ -3995,6 +3996,19 @@ inline void PlatformInit() {
} while (min + 1 < max);
}
#endif // __POSIX__
#ifdef _WIN32
for (int fd = 0; fd <= 2; ++fd) {
auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
if (handle == INVALID_HANDLE_VALUE ||
GetFileType(handle) == FILE_TYPE_UNKNOWN) {
// Ignore _close result. If it fails or not depends on used Windows
// version. We will just check _open result.
_close(fd);
if (fd != _open("nul", _O_RDWR))
ABORT();
}
}
#endif // _WIN32
}


Expand Down
2 changes: 1 addition & 1 deletion src/node_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define NODE_VERSION_IS_LTS 1
#define NODE_VERSION_LTS_CODENAME "Argon"

#define NODE_VERSION_IS_RELEASE 0
#define NODE_VERSION_IS_RELEASE 1

#ifndef NODE_STRINGIFY
#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)
Expand Down
9 changes: 8 additions & 1 deletion src/stream_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,14 @@ class StreamResource {
const uv_buf_t* buf,
uv_handle_type pending,
void* ctx);
typedef void (*DestructCb)(void* ctx);

StreamResource() : bytes_read_(0) {
}
virtual ~StreamResource() = default;
virtual ~StreamResource() {
if (!destruct_cb_.is_empty())
destruct_cb_.fn(destruct_cb_.ctx);
}

virtual int DoShutdown(ShutdownWrap* req_wrap) = 0;
virtual int DoTryWrite(uv_buf_t** bufs, size_t* count);
Expand Down Expand Up @@ -175,15 +179,18 @@ class StreamResource {

inline void set_alloc_cb(Callback<AllocCb> c) { alloc_cb_ = c; }
inline void set_read_cb(Callback<ReadCb> c) { read_cb_ = c; }
inline void set_destruct_cb(Callback<DestructCb> c) { destruct_cb_ = c; }

inline Callback<AfterWriteCb> after_write_cb() { return after_write_cb_; }
inline Callback<AllocCb> alloc_cb() { return alloc_cb_; }
inline Callback<ReadCb> read_cb() { return read_cb_; }
inline Callback<DestructCb> destruct_cb() { return destruct_cb_; }

private:
Callback<AfterWriteCb> after_write_cb_;
Callback<AllocCb> alloc_cb_;
Callback<ReadCb> read_cb_;
Callback<DestructCb> destruct_cb_;
uint64_t bytes_read_;

friend class StreamBase;
Expand Down
4 changes: 2 additions & 2 deletions src/string_bytes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,13 @@ size_t base64_decode_slow(char* dst, size_t dstlen,
size_t k = 0;
for (;;) {
#define V(expr) \
while (i < srclen) { \
for (;;) { \
const uint8_t c = src[i]; \
lo = unbase64(c); \
i += 1; \
if (lo < 64) \
break; /* Legal character. */ \
if (c == '=') \
if (c == '=' || i >= srclen) \
return k; \
} \
expr; \
Expand Down
15 changes: 14 additions & 1 deletion src/tls_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ TLSWrap::TLSWrap(Environment* env,
stream_->set_after_write_cb({ OnAfterWriteImpl, this });
stream_->set_alloc_cb({ OnAllocImpl, this });
stream_->set_read_cb({ OnReadImpl, this });
stream_->set_destruct_cb({ OnDestructImpl, this });

set_alloc_cb({ OnAllocSelf, this });
set_read_cb({ OnReadSelf, this });
Expand Down Expand Up @@ -426,6 +427,12 @@ void TLSWrap::ClearOut() {
memcpy(buf.base, current, avail);
OnRead(avail, &buf);

// Caveat emptor: OnRead() calls into JS land which can result in
// the SSL context object being destroyed. We have to carefully
// check that ssl_ != nullptr afterwards.
if (ssl_ == nullptr)
return;

read -= avail;
current += avail;
}
Expand Down Expand Up @@ -523,7 +530,7 @@ int TLSWrap::GetFD() {


bool TLSWrap::IsAlive() {
return ssl_ != nullptr && stream_->IsAlive();
return ssl_ != nullptr && stream_ != nullptr && stream_->IsAlive();
}


Expand Down Expand Up @@ -661,6 +668,12 @@ void TLSWrap::OnReadImpl(ssize_t nread,
}


void TLSWrap::OnDestructImpl(void* ctx) {
TLSWrap* wrap = static_cast<TLSWrap*>(ctx);
wrap->clear_stream();
}


void TLSWrap::OnAllocSelf(size_t suggested_size, uv_buf_t* buf, void* ctx) {
buf->base = static_cast<char*>(node::Malloc(suggested_size));
CHECK_NE(buf->base, nullptr);
Expand Down
3 changes: 3 additions & 0 deletions src/tls_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class TLSWrap : public AsyncWrap,

size_t self_size() const override { return sizeof(*this); }

void clear_stream() { stream_ = nullptr; }

protected:
static const int kClearOutChunkSize = 16384;

Expand Down Expand Up @@ -119,6 +121,7 @@ class TLSWrap : public AsyncWrap,
const uv_buf_t* buf,
uv_handle_type pending,
void* ctx);
static void OnDestructImpl(void* ctx);

void DoRead(ssize_t nread, const uv_buf_t* buf, uv_handle_type pending);

Expand Down
8 changes: 8 additions & 0 deletions test/fixtures/spawn_closed_stdio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import os
import sys
import subprocess
os.close(0)
os.close(1)
os.close(2)
exit_code = subprocess.call(sys.argv[1:], shell=False)
sys.exit(exit_code)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.string = '$HOME/.node_libraries';

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.string = '$HOME/.node_libraries';

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
'use strict';
console.log(require('foo').string);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.string = '$NODE_PATH';
4 changes: 4 additions & 0 deletions test/parallel/test-buffer-alloc.js
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,10 @@ assert.equal(dot.toString('base64'), '//4uAA==');
// Regression test for https://github.com/nodejs/node/issues/3496.
assert.equal(Buffer.from('=bad'.repeat(1e4), 'base64').length, 0);

// Regression test for https://github.com/nodejs/node/issues/11987.
assert.deepStrictEqual(Buffer.from('w0 ', 'base64'),
Buffer.from('w0', 'base64'));

{
// Creating buffers larger than pool size.
const l = Buffer.poolSize + 5;
Expand Down
Loading