From c2a302c50b3787666339371140ad2c13d50d817a Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Fri, 24 Feb 2017 17:57:45 -0800 Subject: src: do not ignore IDNA conversion error Old behavior can be restored using a special `lenient` mode, as used in the legacy URL parser. PR-URL: https://github.com/nodejs/node/pull/11549 Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- lib/url.js | 5 ++++- src/node_i18n.cc | 20 ++++++++++++++------ src/node_i18n.h | 6 ++++-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/url.js b/lib/url.js index 5d59d3c10f..2db780c7eb 100644 --- a/lib/url.js +++ b/lib/url.js @@ -319,7 +319,10 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { // It only converts parts of the domain name that // have non-ASCII characters, i.e. it doesn't matter if // you call it with a domain that already is ASCII-only. - this.hostname = toASCII(this.hostname); + + // Use lenient mode (`true`) to try to support even non-compliant + // URLs. + this.hostname = toASCII(this.hostname, true); } var p = this.port ? ':' + this.port : ''; diff --git a/src/node_i18n.cc b/src/node_i18n.cc index ae14aed7c6..b337456c63 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -410,7 +410,8 @@ bool InitializeICUDirectory(const std::string& path) { int32_t ToUnicode(MaybeStackBuffer* buf, const char* input, - size_t length) { + size_t length, + bool lenient) { UErrorCode status = U_ZERO_ERROR; uint32_t options = UIDNA_DEFAULT; options |= UIDNA_NONTRANSITIONAL_TO_UNICODE; @@ -435,7 +436,7 @@ int32_t ToUnicode(MaybeStackBuffer* buf, &status); } - if (U_FAILURE(status)) { + if (U_FAILURE(status) || (!lenient && info.errors != 0)) { len = -1; buf->SetLength(0); } else { @@ -448,7 +449,8 @@ int32_t ToUnicode(MaybeStackBuffer* buf, int32_t ToASCII(MaybeStackBuffer* buf, const char* input, - size_t length) { + size_t length, + bool lenient) { UErrorCode status = U_ZERO_ERROR; uint32_t options = UIDNA_DEFAULT; options |= UIDNA_NONTRANSITIONAL_TO_ASCII; @@ -473,7 +475,7 @@ int32_t ToASCII(MaybeStackBuffer* buf, &status); } - if (U_FAILURE(status)) { + if (U_FAILURE(status) || (!lenient && info.errors != 0)) { len = -1; buf->SetLength(0); } else { @@ -489,8 +491,11 @@ static void ToUnicode(const FunctionCallbackInfo& args) { CHECK_GE(args.Length(), 1); CHECK(args[0]->IsString()); Utf8Value val(env->isolate(), args[0]); + // optional arg + bool lenient = args[1]->BooleanValue(env->context()).FromJust(); + MaybeStackBuffer buf; - int32_t len = ToUnicode(&buf, *val, val.length()); + int32_t len = ToUnicode(&buf, *val, val.length(), lenient); if (len < 0) { return env->ThrowError("Cannot convert name to Unicode"); @@ -508,8 +513,11 @@ static void ToASCII(const FunctionCallbackInfo& args) { CHECK_GE(args.Length(), 1); CHECK(args[0]->IsString()); Utf8Value val(env->isolate(), args[0]); + // optional arg + bool lenient = args[1]->BooleanValue(env->context()).FromJust(); + MaybeStackBuffer buf; - int32_t len = ToASCII(&buf, *val, val.length()); + int32_t len = ToASCII(&buf, *val, val.length(), lenient); if (len < 0) { return env->ThrowError("Cannot convert name to ASCII"); diff --git a/src/node_i18n.h b/src/node_i18n.h index 21567eeb3e..270eb1f3d1 100644 --- a/src/node_i18n.h +++ b/src/node_i18n.h @@ -18,10 +18,12 @@ bool InitializeICUDirectory(const std::string& path); int32_t ToASCII(MaybeStackBuffer* buf, const char* input, - size_t length); + size_t length, + bool lenient = false); int32_t ToUnicode(MaybeStackBuffer* buf, const char* input, - size_t length); + size_t length, + bool lenient = false); } // namespace i18n } // namespace node -- cgit v1.2.3