Skip to content

Nodejs runs out of memory trying to connect to HTTPS host with self-signed certificate #37757

Closed
@nils91

Description

  • Version: 15.11.0 (also tested with 12 and 14 on same machine)
  • Platform: Ubuntu 16.04 (Linux 4.4.0-1127.8.2.vz7.151.14 deps: update openssl to 1.0.1j #1 SMP Tue Jun 9 12:58:54 MSK 2020 x86_64 x86_64 x86_64 GNU/Linux)
  • Subsystem: https

What steps will reproduce the bug?

When trying to connect to a https-enabled host and using a self-signed certificate provided to node via NODE_EXTRA_CA_CERTS node hangs for a few minutes, using more and more memory, until it exits with Allocation failed - JavaScript heap out of memory. Full stacktrace below.

How often does it reproduce? Is there a required condition?

The server needs to be up and the correct server certificate needs to be used.

What is the expected behavior?

I would expect the connection to be made successfully, since the self-signed certificate has been provided to node.

What do you see instead?

<--- Last few GCs --->

[15068:0x52f3bd0]   324861 ms: Scavenge (reduce) 4053.6 (4128.3) -> 4053.4 (4129.3) MB, 72.6 / 0.0 ms  (average mu = 0.851, current mu = 0.769) allocation failure
[15068:0x52f3bd0]   325180 ms: Scavenge (reduce) 4054.9 (4129.3) -> 4054.8 (4131.1) MB, 86.6 / 0.0 ms  (average mu = 0.851, current mu = 0.769) allocation failure
[15068:0x52f3bd0]   325442 ms: Scavenge (reduce) 4056.6 (4131.1) -> 4056.4 (4132.6) MB, 71.5 / 0.0 ms  (average mu = 0.851, current mu = 0.769) allocation failure


<--- JS stacktrace --->

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
 1: 0xa7f490 node::Abort() [node]
 2: 0x9a5c4d node::FatalError(char const*, char const*) [node]
 3: 0xc6c2ae v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
 4: 0xc6c627 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xe360a5  [node]
 6: 0xe65633 v8::internal::EvacuateNewSpaceVisitor::Visit(v8::internal::HeapObject, int) [node]
 7: 0xe721e6 v8::internal::FullEvacuator::RawEvacuatePage(v8::internal::MemoryChunk*, long*) [node]
 8: 0xe5e30f v8::internal::Evacuator::EvacuatePage(v8::internal::MemoryChunk*) [node]
 9: 0xe5e588 v8::internal::PageEvacuationTask::RunInParallel(v8::internal::ItemParallelJob::Task::Runner) [node]
10: 0xe503a9 v8::internal::ItemParallelJob::Run() [node]
11: 0xe74170 void v8::internal::MarkCompactCollectorBase::CreateAndExecuteEvacuationTasks<v8::internal::FullEvacuator, v8::internal::MarkCompactCollector>(v8::internal::MarkCompactCollector*, v8::internal::ItemParallelJob*, v8::internal::MigrationObserver*, long) [node]
12: 0xe749b3 v8::internal::MarkCompactCollector::EvacuatePagesInParallel() [node]
13: 0xe74d75 v8::internal::MarkCompactCollector::Evacuate() [node]
14: 0xe874e1 v8::internal::MarkCompactCollector::CollectGarbage() [node]
15: 0xe433a8 v8::internal::Heap::MarkCompact() [node]
16: 0xe44d38 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
17: 0xe482dc v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
18: 0xe0bf3a v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [node]
19: 0xe05444 v8::internal::FactoryBase<v8::internal::Factory>::AllocateRawWithImmortalMap(int, v8::internal::AllocationType, v8::internal::Map, v8::internal::AllocationAlignment) [node]
20: 0xe07540 v8::internal::FactoryBase<v8::internal::Factory>::NewRawOneByteString(int, v8::internal::AllocationType) [node]
21: 0xe1955e v8::internal::Factory::NewStringFromOneByte(v8::internal::Vector<unsigned char const> const&, v8::internal::AllocationType) [node]
22: 0xc839e2 v8::String::NewFromOneByte(v8::Isolate*, unsigned char const*, v8::NewStringType, int) [node]
23: 0xbb5914 node::crypto::GetFingerprintDigest(node::Environment*, evp_md_st const*, x509_st*) [node]
24: 0xbb736e node::crypto::X509ToObject(node::Environment*, x509_st*) [node]
25: 0xbb81e4 node::crypto::GetPeerCert(node::Environment*, std::unique_ptr<ssl_st, node::FunctionDeleter<ssl_st, &SSL_free> > const&, bool, bool) [node]
26: 0xc2b567 node::crypto::TLSWrap::GetPeerCertificate(v8::FunctionCallbackInfo<v8::Value> const&) [node]
27: 0xcd8cbb  [node]
28: 0xcda26c  [node]
29: 0xcda8e6 v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [node]
30: 0x14fa219  [node]
./run.sh: line 5: 15068 Aborted                 node index.js

Additional information

All files i´ve used to reproduce: node_https_test.zip
https_renew_cert.sh is a script used to generate the key/certificate pair. (Sample certificate and key is also included in the zip, so you don´t have to regenerate them, if you don´t have oppenssl installed)
server.js is the server. Execute with node server.js.
index.js is the client. Started from run.sh
run.sh: Starts the client and sets NODE_EXTRA_CA_CERTS. (You need to update the path to the certificate)

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.tlsIssues and PRs related to the tls subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions