From 3fd818c4b59b055ce60ebc8938297ad69cc2e1e8 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Wed, 19 Mar 2025 17:24:46 +0000 Subject: [PATCH] Prevent use of linux-x64 binaries with v1 microarchitecture --- docs/src/content/docs/changelog.md | 2 ++ lib/sharp.js | 12 ++++++++++-- src/sharp.cc | 1 + src/utilities.cc | 17 +++++++++++++++++ src/utilities.h | 1 + 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/src/content/docs/changelog.md b/docs/src/content/docs/changelog.md index 4aee8c21..e66f042f 100644 --- a/docs/src/content/docs/changelog.md +++ b/docs/src/content/docs/changelog.md @@ -24,6 +24,8 @@ Requires libvips v8.16.1 * Expose WebP `smartDeblock` output option. +* Prevent use of linux-x64 binaries with v1 microarchitecture. + * Add `autoOrient` operation and constructor option. [#4151](https://github.com/lovell/sharp/pull/4151) [@happycollision](https://github.com/happycollision) diff --git a/lib/sharp.js b/lib/sharp.js index 3428c5fe..78853e95 100644 --- a/lib/sharp.js +++ b/lib/sharp.js @@ -17,9 +17,9 @@ const paths = [ '@img/sharp-wasm32/sharp.node' ]; -let sharp; +let path, sharp; const errors = []; -for (const path of paths) { +for (path of paths) { try { sharp = require(path); break; @@ -29,6 +29,14 @@ for (const path of paths) { } } +/* istanbul ignore next */ +if (sharp && path.startsWith('@img/sharp-linux-x64') && !sharp._isUsingX64V2()) { + const err = new Error('Prebuilt binaries for linux-x64 require v2 microarchitecture'); + err.code = 'Unsupported CPU'; + errors.push(err); + sharp = null; +} + /* istanbul ignore next */ if (sharp) { module.exports = sharp; diff --git a/src/sharp.cc b/src/sharp.cc index e017b2f3..ed54c501 100644 --- a/src/sharp.cc +++ b/src/sharp.cc @@ -33,6 +33,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) { exports.Set("block", Napi::Function::New(env, block)); exports.Set("_maxColourDistance", Napi::Function::New(env, _maxColourDistance)); exports.Set("_isUsingJemalloc", Napi::Function::New(env, _isUsingJemalloc)); + exports.Set("_isUsingX64V2", Napi::Function::New(env, _isUsingX64V2)); exports.Set("stats", Napi::Function::New(env, stats)); return exports; } diff --git a/src/utilities.cc b/src/utilities.cc index ed84458d..93bd50cd 100644 --- a/src/utilities.cc +++ b/src/utilities.cc @@ -267,3 +267,20 @@ Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info) { return Napi::Boolean::New(env, false); } #endif + +#if defined(__GNUC__) && defined(__x86_64__) +// Are SSE 4.2 intrinsics available at runtime? +Napi::Value _isUsingX64V2(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + unsigned int eax, ebx, ecx, edx; + __asm__ __volatile__("cpuid" + : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) + : "a"(1)); + return Napi::Boolean::New(env, (ecx & 1U << 20) != 0); +} +#else +Napi::Value _isUsingX64V2(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + return Napi::Boolean::New(env, false); +} +#endif diff --git a/src/utilities.h b/src/utilities.h index 0f499ad3..9272f955 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -15,5 +15,6 @@ Napi::Value format(const Napi::CallbackInfo& info); void block(const Napi::CallbackInfo& info); Napi::Value _maxColourDistance(const Napi::CallbackInfo& info); Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info); +Napi::Value _isUsingX64V2(const Napi::CallbackInfo& info); #endif // SRC_UTILITIES_H_