JCMais / node-libcurl

libcurl bindings for Node.js
https://npmjs.org/package/node-libcurl
MIT License
660 stars 117 forks source link

Curl Easy segmentation fault with requests to external site #390

Open nktnet1 opened 1 year ago

nktnet1 commented 1 year ago

Curl Easy segmentation fault with requests to external site

Thank you for this library :). Please let me know if any other information would help.

Describe the bug

I get a segmentation fault when I try to send a request using Curl Easy to an external site such as

There is no issue with localhost/127.0.0.1.

I discovered this when trying to send requests using sync-request-curl in the specific environment with the following inside a Dockerfile:

FROM php:8.1.8-fpm-alpine
RUN apk add --update npm=7.17.0-r0 --repository=http://dl-cdn.alpinelinux.org/alpine/v3.14/main

It seems to work with no issues locally and with other base images, e.g. node:18-alpine.

This was just an environment that was configured at my workplace.

To Reproduce

Code that causes segfault (click to view) ```typescript import { Curl, Easy } from 'node-libcurl'; /* * Simplified from [sync-request-curl](https://github.com/nktnet1/sync-request-curl) */ const request = (method: string, url: string) => { const curl = new Easy(); curl.setOpt(Curl.option.CUSTOMREQUEST, method); curl.setOpt(Curl.option.URL, url); curl.perform(); const statusCode = curl.getInfo('RESPONSE_CODE').data as number; curl.close(); return { statusCode }; }; const localUrl = 'http://localhost:3000'; console.log(`Sending GET request to '${localUrl}' (should get 200)`) const response = request('GET', localUrl); console.log('Status Code:', response.statusCode); console.log(); const externalUrl = 'https://www.google.com' console.log(`Sending GET request to '${externalUrl}' (gets SEGFAULT)`) const segfault = request('GET', externalUrl); console.log('Status Code:', segfault.statusCode); ```

Docker image here. Full repository here.

Have the local server running on one terminal

$ npm start

Then in another terminal run src/request.ts with

$ npm test

> test
> ts-node src/request

Sending GET request to 'http://localhost:3000' (should get 200)
Status Code: 200

Sending GET request to 'https://www.google.com' (gets SEGFAULT)
Segmentation fault

Version information

Node Libcurl Version

3.0.0

Curl Version:

7.83.1

node -e "console.log(require('node-libcurl').Curl.getVersionInfoString())" (click to view) ```shell $ node -e "console.log(require('node-libcurl').Curl.getVersionInfoString())" Version: libcurl/7.86.0 OpenSSL/not available zlib/1.2.12 brotli/1.0.9 zstd/1.4.9 libidn2/2.1.1 libssh2/1.10.0 nghttp2/1.47.0 Protocols: dict, file, ftp, ftps, gopher, gophers, http, https, imap, imaps, ldap, ldaps, mqtt, pop3, pop3s, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp Features: AsynchDNS, Debug, TrackMemory, IDN, IPv6, Largefile, NTLM, NTLM_WB, SSL, libz, brotli, TLS-SRP, HTTP2, UnixSockets, HTTPS-proxy, alt-svc ```

Operating System

Alpine Linux v3.16 x86_64

neofetch output (click to view) ``` $ neofetch --backend off root@2a8a6f86b13b ----------------- OS: Alpine Linux v3.16 x86_64 Host: KVM/QEMU (Standard PC (Q35 + ICH9, 2009) pc-q35-8.0) Kernel: 5.15.49-linuxkit-pr Uptime: 7 hours, 32 mins Packages: 43 (apk) Shell: ash CPU: 11th Gen Intel i7-11370H (4) @ 2.995GHz Memory: 1000MiB / 3774MiB ```

Node.js Version:

18.9.1

npm version output (click to view) ```shell $ npm version { npm: '7.17.0', node: '18.9.1', v8: '10.2.154.15-node.12', uv: '1.44.1', zlib: '1.2.12', brotli: '1.0.9', ares: '1.18.1', modules: '108', nghttp2: '1.47.0', napi: '8', llhttp: '6.0.10', openssl: '1.1.1q', cldr: '41.0', icu: '71.1', tz: '2022a', unicode: '14.0' } ```

Additional Context

This may be related to #198.

cbrichau commented 1 year ago

Same here. Using this package (whether through curly or new Curl()) works on a local URL, but causes a Segmentation fault on an external URL. I'm running Node using docker-compose.

JCMais commented 1 year ago

Hey, thanks for the detailed reproduction steps! Right now I am not finding time to look into this, I know it is usually not feasible, but if possible try using a non-alpine image to see if the issue persists.

jeremydenoun commented 9 months ago

If this can help people about this issue, this is related to openssl version in alpine (3.19 and lower) after analysis deeper the issue (I have the same in my usecase) with segfault handler trapping, I can see this kind of trace

[pc=0x00007f7011cd8d60, sp=0x00007ffe961f1d00] in killpg+0x40
[pc=0x00007f70101ac2a3, sp=0x00007ffe961f2290] in SSL_get_peer_certificate+0x13
[pc=0x00007f7010329027, sp=0x00007ffe961f22a0] in curl_easy_option_next+0x5b17
[pc=0x00007f701032cfee, sp=0x00007ffe961f2cc0] in curl_easy_option_next+0x9ade
[pc=0x00007f701032dff1, sp=0x00007ffe961f2d20] in curl_easy_option_next+0xaae1
[pc=0x00007f70102ec142, sp=0x00007ffe961f2d50] in curl_getenv+0x2ae2
[pc=0x00007f701030303d, sp=0x00007ffe961f2d70] in curl_multi_cleanup+0x74d
[pc=0x00007f7010304522, sp=0x00007ffe961f2de0] in curl_multi_perform+0x312
[pc=0x00007f70103046a4, sp=0x00007ffe961f2f00] in curl_multi_socket_action+0x24
[pc=0x00007f7010383efe, sp=0x00007ffe961f2f20] in NodeLibcurl::Multi::OnSocket(uv_poll_s*, int, int)+0xee
[pc=0x00000000018971bb, sp=0x00007ffe961f3000] in uv__io_poll+0x4db
[pc=0x0000000001883517, sp=0x00007ffe961f6d70] in uv_run+0x187

I switch to debian 12 image (standard or slim) for testing and this work correctly (without segfault)