diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..ef4da0ff58d72ade16ccd791209fbbadec350617 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +firefox-102.11.0esr.b2.processed-source.tar.xz filter=lfs diff=lfs merge=lfs -text +firefox-langpacks-102.11.0esr-20230508.tar.xz filter=lfs diff=lfs merge=lfs -text diff --git a/0001-GLIBCXX-fix-for-GCC-12.patch b/0001-GLIBCXX-fix-for-GCC-12.patch new file mode 100644 index 0000000000000000000000000000000000000000..37d6f500bf03dd5e01060dd117630f69e8d2693d --- /dev/null +++ b/0001-GLIBCXX-fix-for-GCC-12.patch @@ -0,0 +1,44 @@ +From efd5bc0715e5477318be95a76811cda0a89e8289 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= +Date: Fri, 4 Mar 2022 12:00:26 +0100 +Subject: [PATCH] GLIBCXX fix for GCC 12? + +--- + build/unix/stdc++compat/stdc++compat.cpp | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/build/unix/stdc++compat/stdc++compat.cpp b/build/unix/stdc++compat/stdc++compat.cpp +index 0180f6bcfa998..8d7a542ff11f0 100644 +--- a/build/unix/stdc++compat/stdc++compat.cpp ++++ b/build/unix/stdc++compat/stdc++compat.cpp +@@ -24,6 +24,7 @@ + GLIBCXX_3.4.27 is from gcc 10 + GLIBCXX_3.4.28 is from gcc 10 + GLIBCXX_3.4.29 is from gcc 11 ++ GLIBCXX_3.4.30 is from gcc 12 + + This file adds the necessary compatibility tricks to avoid symbols with + version GLIBCXX_3.4.20 and bigger, keeping binary compatibility with +@@ -69,6 +70,19 @@ void __attribute__((weak)) __throw_bad_array_new_length() { MOZ_CRASH(); } + } // namespace std + #endif + ++#if _GLIBCXX_RELEASE >= 12 ++namespace std { ++ ++/* This avoids the GLIBCXX_3.4.30 symbol version. */ ++void __attribute__((weak)) ++__glibcxx_assert_fail(const char* __file, int __line, const char* __function, ++ const char* __condition) { ++ MOZ_CRASH(); ++} ++ ++} // namespace std ++#endif ++ + /* While we generally don't build with exceptions, we have some host tools + * that do use them. libstdc++ from GCC 5.0 added exception constructors with + * char const* argument. Older versions only have a constructor with +-- +2.35.1 + diff --git a/0001-fix-wl_proxy_marshal_flags.patch b/0001-fix-wl_proxy_marshal_flags.patch deleted file mode 100644 index 64c669dbcee430e2e50e7942d2ea91cfbd7bf82f..0000000000000000000000000000000000000000 --- a/0001-fix-wl_proxy_marshal_flags.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 49d1846b55bcd4b54a8b8eb2b4ae0b29be0b36a1 Mon Sep 17 00:00:00 2001 -From: bzg1107 -Date: Tue, 11 Jan 2022 17:36:03 +0800 -Subject: [PATCH] fix wl_proxy_marshal_flags - ---- - widget/gtk/mozwayland/mozwayland.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/widget/gtk/mozwayland/mozwayland.c b/widget/gtk/mozwayland/mozwayland.c -index 5cea1c5..bbf97a5 100644 ---- a/widget/gtk/mozwayland/mozwayland.c -+++ b/widget/gtk/mozwayland/mozwayland.c -@@ -41,6 +41,11 @@ MOZ_EXPORT void wl_proxy_marshal(struct wl_proxy* p, uint32_t opcode, ...) {} - MOZ_EXPORT void wl_proxy_marshal_array(struct wl_proxy* p, uint32_t opcode, - union wl_argument* args) {} - -+MOZ_EXPORT struct wl_proxy *wl_proxy_marshal_flags(struct wl_proxy* proxy, uint32_t opcode, -+ const struct wl_interface *interface, uint32_t version, uint32_t flags, ...) { -+ return NULL; -+} -+ - MOZ_EXPORT struct wl_proxy* wl_proxy_create( - struct wl_proxy* factory, const struct wl_interface* interface) { - return NULL; --- -2.30.0 - diff --git a/Bug-1660901-Support-the-fstat-like-subset-of-fstatat-in-the-Linux-sandbox-policies.patch b/Bug-1660901-Support-the-fstat-like-subset-of-fstatat-in-the-Linux-sandbox-policies.patch deleted file mode 100644 index 173c592d347a8772a487eeedbc3cc843d94fb18d..0000000000000000000000000000000000000000 --- a/Bug-1660901-Support-the-fstat-like-subset-of-fstatat-in-the-Linux-sandbox-policies.patch +++ /dev/null @@ -1,60 +0,0 @@ - -# HG changeset patch -# User Jed Davis -# Date 1598606638 0 -# Node ID a65fc6aca1f2337cb5e8e69f50b539d3c0de95ab -# Parent a6c226548fa02c3ac4681499103cd85217c6de07 -Bug 1660901 - Support the fstat-like subset of fstatat in the Linux sandbox policies. r=gcp, a=RyanVM - -Differential Revision: https://phabricator.services.mozilla.com/D88499 - -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -238,16 +238,22 @@ class SandboxPolicyCommon : public Sandb - } - - static intptr_t StatAtTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast(aux); - auto fd = static_cast(aArgs.args[0]); - auto path = reinterpret_cast(aArgs.args[1]); - auto buf = reinterpret_cast(aArgs.args[2]); - auto flags = static_cast(aArgs.args[3]); -+ -+ if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) != 0 && -+ strcmp(path, "") == 0) { -+ return ConvertError(fstatsyscall(fd, buf)); -+ } -+ - if (fd != AT_FDCWD && path[0] != '/') { - SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)", - fd, path, buf, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } - if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) { - SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)", - (flags & ~AT_SYMLINK_NOFOLLOW), fd, path, buf, flags); -diff --git a/security/sandbox/linux/broker/SandboxBrokerUtils.h b/security/sandbox/linux/broker/SandboxBrokerUtils.h ---- a/security/sandbox/linux/broker/SandboxBrokerUtils.h -+++ b/security/sandbox/linux/broker/SandboxBrokerUtils.h -@@ -14,17 +14,19 @@ - // On 32-bit Linux, stat calls are translated by libc into stat64 - // calls. We'll intercept those and handle them in the stat functions - // but must be sure to use the right structure layout. - - #if defined(__NR_stat64) - typedef struct stat64 statstruct; - # define statsyscall stat64 - # define lstatsyscall lstat64 -+# define fstatsyscall fstat64 - #elif defined(__NR_stat) - typedef struct stat statstruct; - # define statsyscall stat - # define lstatsyscall lstat -+# define fstatsyscall fstat - #else - # error Missing stat syscall include. - #endif - - #endif // mozilla_SandboxBrokerUtils_h - diff --git a/Bug-1660901-ignore-AT_NO_AUTOMOUNT-in-fstatat-system-call.patch b/Bug-1660901-ignore-AT_NO_AUTOMOUNT-in-fstatat-system-call.patch deleted file mode 100644 index 1fcf1b815da54c23907ff2267289c489493c40fd..0000000000000000000000000000000000000000 --- a/Bug-1660901-ignore-AT_NO_AUTOMOUNT-in-fstatat-system-call.patch +++ /dev/null @@ -1,40 +0,0 @@ - -# HG changeset patch -# User Julien Cristau -# Date 1599423639 0 -# Node ID 8ecb82a2f65cf6082d50d1e00453fbeba97633fb -# Parent 0ce38d3c2aa2357df4a8fcc5fd39d3af05fce7e1 -Bug 1660901 - ignore AT_NO_AUTOMOUNT in fstatat system call. r=jld, a=RyanVM - -Per the manpage "Both stat() and lstat() act as though AT_NO_AUTOMOUNT -was set.", so don't bail if it's set in a call to fstatat. - -Differential Revision: https://phabricator.services.mozilla.com/D89121 - -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -249,19 +249,20 @@ class SandboxPolicyCommon : public Sandb - return ConvertError(fstatsyscall(fd, buf)); - } - - if (fd != AT_FDCWD && path[0] != '/') { - SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)", - fd, path, buf, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } -- if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) { -+ if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) { - SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)", -- (flags & ~AT_SYMLINK_NOFOLLOW), fd, path, buf, flags); -+ (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)), fd, -+ path, buf, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } - return (flags & AT_SYMLINK_NOFOLLOW) == 0 ? broker->Stat(path, buf) - : broker->LStat(path, buf); - } - - static intptr_t ChmodTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast(aux); - diff --git a/Bug-1673202-Call-fstat-directly-in-Linux-sandbox-fstatat-interception.patch b/Bug-1673202-Call-fstat-directly-in-Linux-sandbox-fstatat-interception.patch deleted file mode 100644 index 0687e7db90f3e3d66f1d103ae5496c2de80dde0c..0000000000000000000000000000000000000000 --- a/Bug-1673202-Call-fstat-directly-in-Linux-sandbox-fstatat-interception.patch +++ /dev/null @@ -1,48 +0,0 @@ - -# HG changeset patch -# User Jed Davis -# Date 1603832709 0 -# Node ID 13d5867b039948a79fa80fc2081a17b8089f1ed7 -# Parent 0322427df80a91fdeace25c1508105074dc8adad -Bug 1673202 - Call fstat directly in Linux sandbox fstatat interception. r=gcp, a=RyanVM - -Sandbox policies handle the case of `fstatat(fd, "", AT_EMPTY_PATH|...)` -by invoking the SIGSYS handler (because seccomp-bpf can't tell if the -string will be empty when the syscall would use it), which makes the -equivalent call to `fstat`. - -Unfortunately, recent development versions of glibc implement `fstat` by -calling `fstatat`, which causes unbounded recursion and stack overflow. -(This depends on the headers present at build time; see the bug for more -details.) This patch switches it to use the `fstat` (or `fstat64` on -32-bit) syscall directly. - -Differential Revision: https://phabricator.services.mozilla.com/D94798 - -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -241,17 +241,21 @@ class SandboxPolicyCommon : public Sandb - auto broker = static_cast(aux); - auto fd = static_cast(aArgs.args[0]); - auto path = reinterpret_cast(aArgs.args[1]); - auto buf = reinterpret_cast(aArgs.args[2]); - auto flags = static_cast(aArgs.args[3]); - - if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) != 0 && - strcmp(path, "") == 0) { -- return ConvertError(fstatsyscall(fd, buf)); -+#ifdef __NR_fstat64 -+ return DoSyscall(__NR_fstat64, fd, buf); -+#else -+ return DoSyscall(__NR_fstat, fd, buf); -+#endif - } - - if (fd != AT_FDCWD && path[0] != '/') { - SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)", - fd, path, buf, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } - if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) { - diff --git a/Bug-1673770-Extend-the-handling-of-fstatat-as-fstat-to-sandboxes-that-dont-use-a-file-broker.patch b/Bug-1673770-Extend-the-handling-of-fstatat-as-fstat-to-sandboxes-that-dont-use-a-file-broker.patch deleted file mode 100644 index ae9e8936020347f93cd4f30275ad649e9f4976a0..0000000000000000000000000000000000000000 --- a/Bug-1673770-Extend-the-handling-of-fstatat-as-fstat-to-sandboxes-that-dont-use-a-file-broker.patch +++ /dev/null @@ -1,85 +0,0 @@ - -# HG changeset patch -# User Jed Davis -# Date 1603993288 0 -# Node ID 3962fa9f3084c5bca8458cecdaac664dc431164a -# Parent 4e708898d49e078de5f946d03b0627779b282fd0 -Bug 1673770 - Extend the handling of fstatat-as-fstat to sandboxes that don't use a file broker. r=gcp, a=RyanVM - -The fix for bug 1660901, to handle the subset of fstatat that is -equivalent to fstat, was incomplete: it was added to the existing -hook for the file broker, so processes that don't use a broker (like -GMP) didn't get the fix. That wasn't a problem when the only use of -that feature was in content processes via GTK, but now that glibc has -reimplemented fstat that way, it's necessary for all processes. - -Differential Revision: https://phabricator.services.mozilla.com/D95108 - -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -248,16 +248,20 @@ class SandboxPolicyCommon : public Sandb - strcmp(path, "") == 0) { - #ifdef __NR_fstat64 - return DoSyscall(__NR_fstat64, fd, buf); - #else - return DoSyscall(__NR_fstat, fd, buf); - #endif - } - -+ if (!broker) { -+ return BlockedSyscallTrap(aArgs, nullptr); -+ } -+ - if (fd != AT_FDCWD && path[0] != '/') { - SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)", - fd, path, buf, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } - if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) { - SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)", - (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)), fd, -@@ -442,17 +446,17 @@ class SandboxPolicyCommon : public Sandb - return Nothing(); - } - } - - ResultExpr EvaluateSyscall(int sysno) const override { - // If a file broker client was provided, route syscalls to it; - // otherwise, fall through to the main policy, which will deny - // them. -- if (mBroker != nullptr) { -+ if (mBroker) { - switch (sysno) { - case __NR_open: - return Trap(OpenTrap, mBroker); - case __NR_openat: - return Trap(OpenAtTrap, mBroker); - case __NR_access: - return Trap(AccessTrap, mBroker); - case __NR_faccessat: -@@ -481,16 +485,23 @@ class SandboxPolicyCommon : public Sandb - return Trap(RmdirTrap, mBroker); - case __NR_unlink: - return Trap(UnlinkTrap, mBroker); - case __NR_readlink: - return Trap(ReadlinkTrap, mBroker); - case __NR_readlinkat: - return Trap(ReadlinkAtTrap, mBroker); - } -+ } else { -+ // In the absence of a broker we still need to handle the -+ // fstat-equivalent subset of fstatat; see bug 1673770. -+ switch (sysno) { -+ CASES_FOR_fstatat: -+ return Trap(StatAtTrap, nullptr); -+ } - } - - switch (sysno) { - // Timekeeping - case __NR_clock_nanosleep: - case __NR_clock_getres: - #ifdef __NR_clock_gettime64 - case __NR_clock_gettime64: - diff --git a/Bug-1680166-GCC-is-smarter-than-clang-so-ignore-the-warning-properly.patch b/Bug-1680166-GCC-is-smarter-than-clang-so-ignore-the-warning-properly.patch deleted file mode 100644 index 6af527e2f9825ab56df289607c2363f11e47b0b9..0000000000000000000000000000000000000000 --- a/Bug-1680166-GCC-is-smarter-than-clang-so-ignore-the-warning-properly.patch +++ /dev/null @@ -1,46 +0,0 @@ - -# HG changeset patch -# User Emilio Cobos Álvarez -# Date 1606915787 -3600 -# Node ID 8aa3952dd7208d96648ea171f814c748ec027630 -# Parent ff436849850a87dfa3db032e80eaba5e5a3536f4 -Bug 1680166 - GCC is smarter than clang, so ignore the warning properly. a=RyanVM - -diff --git a/security/sandbox/linux/gtest/TestBroker.cpp b/security/sandbox/linux/gtest/TestBroker.cpp ---- a/security/sandbox/linux/gtest/TestBroker.cpp -+++ b/security/sandbox/linux/gtest/TestBroker.cpp -@@ -212,23 +212,27 @@ TEST_F(SandboxBrokerTest, Access) { - - TEST_F(SandboxBrokerTest, Stat) { - statstruct realStat, brokeredStat; - ASSERT_EQ(0, statsyscall("/dev/null", &realStat)) << "Shouldn't ever fail!"; - EXPECT_EQ(0, Stat("/dev/null", &brokeredStat)); - EXPECT_EQ(realStat.st_ino, brokeredStat.st_ino); - EXPECT_EQ(realStat.st_rdev, brokeredStat.st_rdev); - -- // Add some indirection to avoid -Wnonnull warnings. -- [&](const char* aPath) { -- EXPECT_EQ(-1, statsyscall(aPath, &realStat)); -- EXPECT_EQ(errno, EFAULT); -+#if defined(__clang__) || defined(__GNUC__) -+# pragma GCC diagnostic push -+# pragma GCC diagnostic ignored "-Wnonnull" -+#endif -+ EXPECT_EQ(-1, statsyscall(nullptr, &realStat)); -+ EXPECT_EQ(errno, EFAULT); - -- EXPECT_EQ(-EFAULT, Stat(aPath, &brokeredStat)); -- }(nullptr); -+ EXPECT_EQ(-EFAULT, Stat(nullptr, &brokeredStat)); -+#if defined(__clang__) || defined(__GNUC__) -+# pragma GCC diagnostic pop -+#endif - - EXPECT_EQ(-ENOENT, Stat("/var/empty/qwertyuiop", &brokeredStat)); - EXPECT_EQ(-EACCES, Stat("/dev", &brokeredStat)); - - EXPECT_EQ(0, Stat("/proc/self", &brokeredStat)); - EXPECT_TRUE(S_ISDIR(brokeredStat.st_mode)); - } - - diff --git a/Bug-1680166-Return-EFAULT-when-given-a-null-path-to-stat-calls-in-the-sandbox-filter.patch b/Bug-1680166-Return-EFAULT-when-given-a-null-path-to-stat-calls-in-the-sandbox-filter.patch deleted file mode 100644 index 10587bcb1175a5c085e56dbf98df63c9974017fe..0000000000000000000000000000000000000000 --- a/Bug-1680166-Return-EFAULT-when-given-a-null-path-to-stat-calls-in-the-sandbox-filter.patch +++ /dev/null @@ -1,120 +0,0 @@ - -# HG changeset patch -# User Emilio Cobos Álvarez -# Date 1606907116 0 -# Node ID ff436849850a87dfa3db032e80eaba5e5a3536f4 -# Parent f326cd8f9f19a8f3b5edf9d6838fdce5b02d9c64 -Bug 1680166 - Return EFAULT when given a null path to stat* calls in the sandbox filter. r=gcp, a=RyanVM - -It's a common way to check the existence of system calls. Glibc may fall -back to fstatat when statx is called, passing down the null path. - -Since we handle fstatat, let's return -EFAULT the same way the real -fstatat syscall would do. - -This is needed for the sandbox not to constantly crash due to this statx -call in rustc: - -https://github.com/rust-lang/rust/blob/09c9c9f7da72b774cc445c0f56fc0b9792a49647/library/std/src/sys/unix/fs.rs#L119-L123 - -Differential Revision: https://phabricator.services.mozilla.com/D98414 - -diff --git a/security/sandbox/linux/SandboxBrokerClient.cpp b/security/sandbox/linux/SandboxBrokerClient.cpp ---- a/security/sandbox/linux/SandboxBrokerClient.cpp -+++ b/security/sandbox/linux/SandboxBrokerClient.cpp -@@ -154,21 +154,29 @@ int SandboxBrokerClient::Open(const char - } - - int SandboxBrokerClient::Access(const char* aPath, int aMode) { - Request req = {SANDBOX_FILE_ACCESS, aMode, 0}; - return DoCall(&req, aPath, nullptr, nullptr, false); - } - - int SandboxBrokerClient::Stat(const char* aPath, statstruct* aStat) { -+ if (!aPath || !aStat) { -+ return -EFAULT; -+ } -+ - Request req = {SANDBOX_FILE_STAT, 0, sizeof(statstruct)}; - return DoCall(&req, aPath, nullptr, (void*)aStat, false); - } - - int SandboxBrokerClient::LStat(const char* aPath, statstruct* aStat) { -+ if (!aPath || !aStat) { -+ return -EFAULT; -+ } -+ - Request req = {SANDBOX_FILE_STAT, O_NOFOLLOW, sizeof(statstruct)}; - return DoCall(&req, aPath, nullptr, (void*)aStat, false); - } - - int SandboxBrokerClient::Chmod(const char* aPath, int aMode) { - Request req = {SANDBOX_FILE_CHMOD, aMode, 0}; - return DoCall(&req, aPath, nullptr, nullptr, false); - } -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -239,30 +239,30 @@ class SandboxPolicyCommon : public Sandb - - static intptr_t StatAtTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast(aux); - auto fd = static_cast(aArgs.args[0]); - auto path = reinterpret_cast(aArgs.args[1]); - auto buf = reinterpret_cast(aArgs.args[2]); - auto flags = static_cast(aArgs.args[3]); - -- if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) != 0 && -- strcmp(path, "") == 0) { -+ if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) && path && -+ !strcmp(path, "")) { - #ifdef __NR_fstat64 - return DoSyscall(__NR_fstat64, fd, buf); - #else - return DoSyscall(__NR_fstat, fd, buf); - #endif - } - - if (!broker) { - return BlockedSyscallTrap(aArgs, nullptr); - } - -- if (fd != AT_FDCWD && path[0] != '/') { -+ if (fd != AT_FDCWD && path && path[0] != '/') { - SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)", - fd, path, buf, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } - if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) { - SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)", - (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)), fd, - path, buf, flags); -diff --git a/security/sandbox/linux/gtest/TestBroker.cpp b/security/sandbox/linux/gtest/TestBroker.cpp ---- a/security/sandbox/linux/gtest/TestBroker.cpp -+++ b/security/sandbox/linux/gtest/TestBroker.cpp -@@ -212,16 +212,24 @@ TEST_F(SandboxBrokerTest, Access) { - - TEST_F(SandboxBrokerTest, Stat) { - statstruct realStat, brokeredStat; - ASSERT_EQ(0, statsyscall("/dev/null", &realStat)) << "Shouldn't ever fail!"; - EXPECT_EQ(0, Stat("/dev/null", &brokeredStat)); - EXPECT_EQ(realStat.st_ino, brokeredStat.st_ino); - EXPECT_EQ(realStat.st_rdev, brokeredStat.st_rdev); - -+ // Add some indirection to avoid -Wnonnull warnings. -+ [&](const char* aPath) { -+ EXPECT_EQ(-1, statsyscall(aPath, &realStat)); -+ EXPECT_EQ(errno, EFAULT); -+ -+ EXPECT_EQ(-EFAULT, Stat(aPath, &brokeredStat)); -+ }(nullptr); -+ - EXPECT_EQ(-ENOENT, Stat("/var/empty/qwertyuiop", &brokeredStat)); - EXPECT_EQ(-EACCES, Stat("/dev", &brokeredStat)); - - EXPECT_EQ(0, Stat("/proc/self", &brokeredStat)); - EXPECT_TRUE(S_ISDIR(brokeredStat.st_mode)); - } - - TEST_F(SandboxBrokerTest, LStat) { - diff --git a/CVE-2020-15664.patch b/CVE-2020-15664.patch deleted file mode 100644 index 3c0c5f8369dfe554a2e6ecf769b4b4f332596990..0000000000000000000000000000000000000000 --- a/CVE-2020-15664.patch +++ /dev/null @@ -1,34 +0,0 @@ -# HG changeset patch -# User Kris Maglione -# Date 1597420945 0 -# Fri Aug 14 16:02:25 2020 +0000 -# Node ID 1edd9346c110b011ed87e50eb3d417202ea445fb -# Parent f69f80e5659f11977e7f1bd48386ea22e921dd52 -Bug 1658214: Only construct JS-implemented objects if inner window is current. r=bholley - -Differential Revision: https://phabricator.services.mozilla.com/D86614 - -diff -r f69f80e5659f -r 1edd9346c110 dom/bindings/BindingUtils.cpp ---- a/dom/bindings/BindingUtils.cpp Fri Aug 14 15:57:45 2020 +0000 -+++ b/dom/bindings/BindingUtils.cpp Fri Aug 14 16:02:25 2020 +0000 -@@ -2547,6 +2547,12 @@ - { - AutoNoJSAPI nojsapi; - -+ nsCOMPtr window = do_QueryInterface(aGlobal); -+ if (!window->IsCurrentInnerWindow()) { -+ aRv.ThrowInvalidStateError("Window no longer active"); -+ return; -+ } -+ - // Get the XPCOM component containing the JS implementation. - nsresult rv; - nsCOMPtr implISupports = do_CreateInstance(aContractId, &rv); -@@ -2561,7 +2567,6 @@ - // and our global is a window. - nsCOMPtr gpi = - do_QueryInterface(implISupports); -- nsCOMPtr window = do_QueryInterface(aGlobal); - if (gpi) { - JS::Rooted initReturn(RootingCx()); - rv = gpi->Init(window, &initReturn); diff --git a/CVE-2020-15665.patch b/CVE-2020-15665.patch deleted file mode 100644 index fda950f7e6057538fd9d192b1aef803725d9e2d5..0000000000000000000000000000000000000000 --- a/CVE-2020-15665.patch +++ /dev/null @@ -1,137 +0,0 @@ -# HG changeset patch -# User Gijs Kruitbosch -# Date 1594843114 0 -# Wed Jul 15 19:58:34 2020 +0000 -# Node ID 8079eea73df334803da5b07322b19d32aa8ed9e3 -# Parent 8dee8cb525a2c7cff36a89be107eb50628619201 -Bug 1651636 - reset the address bar when beforeunload prompts close, r=mak - -Differential Revision: https://phabricator.services.mozilla.com/D83213 - -diff -r 8dee8cb525a2 -r 8079eea73df3 browser/actors/PromptParent.jsm ---- a/browser/actors/PromptParent.jsm Wed Jul 15 19:45:37 2020 +0000 -+++ b/browser/actors/PromptParent.jsm Wed Jul 15 19:58:34 2020 +0000 -@@ -169,7 +169,10 @@ - - this.unregisterPrompt(id); - -- PromptUtils.fireDialogEvent(window, "DOMModalDialogClosed", browser); -+ PromptUtils.fireDialogEvent(window, "DOMModalDialogClosed", browser, { -+ wasPermitUnload: args.inPermitUnload, -+ areLeaving: args.ok, -+ }); - resolver(args); - browser.maybeLeaveModalState(); - }; -diff -r 8dee8cb525a2 -r 8079eea73df3 browser/base/content/tabbrowser.js ---- a/browser/base/content/tabbrowser.js Wed Jul 15 19:45:37 2020 +0000 -+++ b/browser/base/content/tabbrowser.js Wed Jul 15 19:58:34 2020 +0000 -@@ -5418,6 +5418,26 @@ - true - ); - -+ // When cancelling beforeunload tabmodal dialogs, reset the URL bar to -+ // avoid spoofing risks. -+ this.addEventListener( -+ "DOMModalDialogClosed", -+ event => { -+ if ( -+ !event.detail?.wasPermitUnload || -+ event.detail.areLeaving || -+ event.target.nodeName != "browser" -+ ) { -+ return; -+ } -+ event.target.userTypedValue = null; -+ if (event.target == this.selectedBrowser) { -+ gURLBar.setURI(); -+ } -+ }, -+ true -+ ); -+ - let onTabCrashed = event => { - if (!event.isTrusted || !event.isTopFrame) { - return; -diff -r 8dee8cb525a2 -r 8079eea73df3 browser/base/content/test/tabPrompts/browser.ini ---- a/browser/base/content/test/tabPrompts/browser.ini Wed Jul 15 19:45:37 2020 +0000 -+++ b/browser/base/content/test/tabPrompts/browser.ini Wed Jul 15 19:58:34 2020 +0000 -@@ -1,3 +1,5 @@ -+[browser_beforeunload_urlbar.js] -+support-files = file_beforeunload_stop.html - [browser_closeTabSpecificPanels.js] - skip-if = (verify && debug && (os == 'linux')) || (fission && os == 'linux' && bits == 64 && os_version == '18.04') # Bug 1548664 - [browser_multiplePrompts.js] -diff -r 8dee8cb525a2 -r 8079eea73df3 browser/base/content/test/tabPrompts/browser_beforeunload_urlbar.js ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/browser/base/content/test/tabPrompts/browser_beforeunload_urlbar.js Wed Jul 15 19:58:34 2020 +0000 -@@ -0,0 +1,57 @@ -+/* Any copyright is dedicated to the Public Domain. -+ http://creativecommons.org/publicdomain/zero/1.0/ */ -+ -+"use strict"; -+ -+const TEST_ROOT = getRootDirectory(gTestPath).replace( -+ "chrome://mochitests/content", -+ "http://example.com" -+); -+ -+add_task(async function test_beforeunload_stay_clears_urlbar() { -+ await SpecialPowers.pushPrefEnv({ -+ set: [["dom.require_user_interaction_for_beforeunload", false]], -+ }); -+ const TEST_URL = TEST_ROOT + "file_beforeunload_stop.html"; -+ await BrowserTestUtils.withNewTab(TEST_URL, async function(browser) { -+ gURLBar.focus(); -+ const inputValue = "http://example.org/?q=typed"; -+ gURLBar.inputField.value = inputValue.slice(0, -1); -+ EventUtils.sendString(inputValue.slice(-1)); -+ -+ let promptOpenedPromise = TestUtils.topicObserved("tabmodal-dialog-loaded"); -+ EventUtils.synthesizeKey("VK_RETURN"); -+ await promptOpenedPromise; -+ let promptElement = browser.parentNode.querySelector("tabmodalprompt"); -+ -+ // Click the cancel button -+ promptElement.querySelector(".tabmodalprompt-button1").click(); -+ -+ await TestUtils.waitForCondition( -+ () => promptElement.parentNode == null, -+ "tabprompt should be removed" -+ ); -+ // Can't just compare directly with TEST_URL because the URL may be trimmed. -+ // Just need it to not be the example.org thing we typed in. -+ ok( -+ gURLBar.value.endsWith("_stop.html"), -+ "Url bar should be reset to point to the stop html file" -+ ); -+ ok( -+ gURLBar.value.includes("example.com"), -+ "Url bar should be reset to example.com" -+ ); -+ // Check the lock/identity icons are back: -+ is( -+ gURLBar.textbox.getAttribute("pageproxystate"), -+ "valid", -+ "Should be in valid pageproxy state." -+ ); -+ -+ // Now we need to get rid of the handler to avoid the prompt coming up when trying to close the -+ // tab when we exit `withNewTab`. :-) -+ await SpecialPowers.spawn(browser, [], function() { -+ content.window.onbeforeunload = null; -+ }); -+ }); -+}); -diff -r 8dee8cb525a2 -r 8079eea73df3 browser/base/content/test/tabPrompts/file_beforeunload_stop.html ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/browser/base/content/test/tabPrompts/file_beforeunload_stop.html Wed Jul 15 19:58:34 2020 +0000 -@@ -0,0 +1,8 @@ -+ -+

I will ask not to be closed.

-+ -+ diff --git a/CVE-2020-15666.patch b/CVE-2020-15666.patch deleted file mode 100644 index 61460f88b046e5e65f1a61b9a5f978a13c402039..0000000000000000000000000000000000000000 --- a/CVE-2020-15666.patch +++ /dev/null @@ -1,113 +0,0 @@ -# HG changeset patch -# User Sebastian Streich -# Date 1594901018 0 -# Thu Jul 16 12:03:38 2020 +0000 -# Node ID b8f37ab6318150a94022625b0500efce2c456947 -# Parent 7e7affa995d31d0325c26d7a9994971e7682f3a0 -Bug 1450853 - Use Generic Error for 3rdparty MediaElement r=ckerschb,smaug - -*** -Add test - -Differential Revision: https://phabricator.services.mozilla.com/D80080 - -diff -r 7e7affa995d3 -r b8f37ab63181 dom/html/HTMLMediaElement.cpp ---- a/dom/html/HTMLMediaElement.cpp Thu Jul 16 12:23:08 2020 +0000 -+++ b/dom/html/HTMLMediaElement.cpp Thu Jul 16 12:03:38 2020 +0000 -@@ -2354,7 +2354,24 @@ - if (mDecoder) { - ShutdownDecoder(); - } -- mErrorSink->SetError(MEDIA_ERR_SRC_NOT_SUPPORTED, aErrorDetails); -+ -+ bool isThirdPartyLoad = false; -+ nsresult rv = NS_ERROR_NOT_AVAILABLE; -+ if (mSrcAttrTriggeringPrincipal) { -+ rv = mSrcAttrTriggeringPrincipal->IsThirdPartyURI(mLoadingSrc, -+ &isThirdPartyLoad); -+ } -+ -+ if (NS_SUCCEEDED(rv) && isThirdPartyLoad) { -+ // aErrorDetails can include sensitive details like MimeType or HTTP Status -+ // Code. In case we're loading a 3rd party resource we should not leak this -+ // and pass a Generic Error Message -+ mErrorSink->SetError(MEDIA_ERR_SRC_NOT_SUPPORTED, -+ NS_LITERAL_CSTRING("Failed to open media")); -+ } else { -+ mErrorSink->SetError(MEDIA_ERR_SRC_NOT_SUPPORTED, aErrorDetails); -+ } -+ - RemoveMediaTracks(); - ChangeDelayLoadStatus(false); - UpdateAudioChannelPlayingState(); -diff -r 7e7affa995d3 -r b8f37ab63181 dom/security/test/general/mochitest.ini ---- a/dom/security/test/general/mochitest.ini Thu Jul 16 12:23:08 2020 +0000 -+++ b/dom/security/test/general/mochitest.ini Thu Jul 16 12:03:38 2020 +0000 -@@ -63,3 +63,4 @@ - [test_sec_fetch_websocket.html] - skip-if = toolkit == 'android' # no websocket support Bug 982828 - support-files = file_sec_fetch_websocket_wsh.py -+[test_bug1450853.html] -\ No newline at end of file -diff -r 7e7affa995d3 -r b8f37ab63181 dom/security/test/general/test_bug1450853.html ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/dom/security/test/general/test_bug1450853.html Thu Jul 16 12:03:38 2020 +0000 -@@ -0,0 +1,58 @@ -+ -+ -+ -+ -+ -+Test for Cross-origin resouce status leak via MediaError -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Mozilla Bug 1450853 -+ -+ -+ diff --git a/CVE-2020-15667.patch b/CVE-2020-15667.patch deleted file mode 100644 index 81adc8f7554d07d65b37ea51c539d714905e3786..0000000000000000000000000000000000000000 --- a/CVE-2020-15667.patch +++ /dev/null @@ -1,22 +0,0 @@ -# HG changeset patch -# User Molly Howell -# Date 1595024754 0 -# Fri Jul 17 22:25:54 2020 +0000 -# Node ID b79b6cc78248eea7fda10bfb76aa273c19c9fa65 -# Parent 0c0f777161a9499dd149853ff62d356f75d16c2a -Bug 1653371 - Don't used a signed type for a length parameter. r=bytesized - -Differential Revision: https://phabricator.services.mozilla.com/D84031 - -diff -r 0c0f777161a9 -r b79b6cc78248 modules/libmar/src/mar_read.c ---- a/modules/libmar/src/mar_read.c Sat Jul 18 02:57:28 2020 +0300 -+++ b/modules/libmar/src/mar_read.c Fri Jul 17 22:25:54 2020 +0000 -@@ -26,7 +26,7 @@ - return CityHash64(name, strlen(name)) % TABLESIZE; - } - --static int mar_insert_item(MarFile* mar, const char* name, int namelen, -+static int mar_insert_item(MarFile* mar, const char* name, uint32_t namelen, - uint32_t offset, uint32_t length, uint32_t flags) { - MarItem *item, *root; - uint32_t hash; diff --git a/CVE-2020-15668.patch b/CVE-2020-15668.patch deleted file mode 100644 index 7d75844d0a25c984ec2052738d8cfe087f287e49..0000000000000000000000000000000000000000 --- a/CVE-2020-15668.patch +++ /dev/null @@ -1,38 +0,0 @@ -# HG changeset patch -# User Kevin Jacobs -# Date 1594335948 0 -# Thu Jul 09 23:05:48 2020 +0000 -# Node ID 06be9b59deb034f3ec6ab93c55e3ba4039f690cd -# Parent 93092fe1e43c69a0b7e7b2960b4b55524ba30db0 -Bug 1651520 - slotLock race in NSC_GetTokenInfo r=kjacobs -2020-07-09 J.C. Jones - - * lib/softoken/pkcs11.c: - Bug 1651520 - slotLock race in NSC_GetTokenInfo r=kjacobs - - Basically, NSC_GetTokenInfo doesn't lock slot->slotLock before - accessing slot after obtaining it, even though slotLock is defined - as its lock. [0] - - [0] https://searchfox.org/nss/rev/a412e70e55218aaf670f1f10322fa734d8 - a9fbde/lib/softoken/pkcs11i.h#320-321 - [58c2abd7404e] [tip] - -diff -r 93092fe1e43c -r 06be9b59deb0 security/nss/lib/softoken/pkcs11.c ---- a/security/nss/lib/softoken/pkcs11.c Thu Jul 09 23:16:09 2020 +0000 -+++ b/security/nss/lib/softoken/pkcs11.c Thu Jul 09 23:05:48 2020 +0000 -@@ -3661,10 +3661,12 @@ - PORT_Memcpy(pInfo->model, "NSS 3 ", 16); - PORT_Memcpy(pInfo->serialNumber, "0000000000000000", 16); - PORT_Memcpy(pInfo->utcTime, "0000000000000000", 16); -- pInfo->ulMaxSessionCount = 0; /* arbitrarily large */ -+ pInfo->ulMaxSessionCount = 0; /* arbitrarily large */ -+ pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */ -+ PZ_Lock(slot->slotLock); /* Protect sessionCount / rwSessioncount */ - pInfo->ulSessionCount = slot->sessionCount; -- pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */ - pInfo->ulRwSessionCount = slot->rwSessionCount; -+ PZ_Unlock(slot->slotLock); /* Unlock before sftk_getKeyDB */ - pInfo->firmwareVersion.major = 0; - pInfo->firmwareVersion.minor = 0; - PORT_Memcpy(pInfo->label, slot->tokDescription, sizeof(pInfo->label)); diff --git a/CVE-2020-15676.patch b/CVE-2020-15676.patch deleted file mode 100644 index 55c8dbef8605eccda46fdc51020940349aded71a..0000000000000000000000000000000000000000 --- a/CVE-2020-15676.patch +++ /dev/null @@ -1,23 +0,0 @@ -# HG changeset patch -# User Kagami Sascha Rosylight -# Date 1599489912 0 -# Mon Sep 07 14:45:12 2020 +0000 -# Node ID 67c242c00ce3e796dafb7e98bbbf025e29cc1c67 -# Parent 749fda4e5eb11918833fa57e25adc77e4ed1db95 -Bug 1646140 - Fire SVG onload only when scripting is enabled r=hsivonen - -Differential Revision: https://phabricator.services.mozilla.com/D89218 - -diff -r 749fda4e5eb1 -r 67c242c00ce3 parser/html/nsHtml5TreeBuilderCppSupplement.h ---- a/parser/html/nsHtml5TreeBuilderCppSupplement.h Mon Sep 07 13:35:31 2020 +0000 -+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h Mon Sep 07 14:45:12 2020 +0000 -@@ -1072,6 +1072,9 @@ - } - if (aNamespace == kNameSpaceID_SVG) { - if (aName == nsGkAtoms::svg) { -+ if (!scriptingEnabled || mPreventScriptExecution) { -+ return; -+ } - if (mBuilder) { - nsHtml5TreeOperation::SvgLoad(static_cast(aElement)); - return; diff --git a/CVE-2020-15677.patch b/CVE-2020-15677.patch deleted file mode 100644 index 2cac5a210312fc03eed5e91cf1c70f8d84dd3ad4..0000000000000000000000000000000000000000 --- a/CVE-2020-15677.patch +++ /dev/null @@ -1,30 +0,0 @@ -# HG changeset patch -# User Gijs Kruitbosch -# Date 1597251031 0 -# Wed Aug 12 16:50:31 2020 +0000 -# Node ID 082de8244278d76f9d6d216a7fd5da772b5152d3 -# Parent cc6db3162f6e3e9cdb85749054b52074b78c1643 -Bug 1641487, r=jaws - -Differential Revision: https://phabricator.services.mozilla.com/D86761 - -diff -r cc6db3162f6e -r 082de8244278 browser/components/downloads/DownloadsViewUI.jsm ---- a/browser/components/downloads/DownloadsViewUI.jsm Wed Aug 12 14:52:18 2020 +0000 -+++ b/browser/components/downloads/DownloadsViewUI.jsm Wed Aug 12 16:50:31 2020 +0000 -@@ -342,15 +342,7 @@ - * Downloads View. Type is either l10n object or string literal. - */ - showStatusWithDetails(stateLabel, hoverStatus) { -- let referrer = -- this.download.source.referrerInfo && -- this.download.source.referrerInfo.originalReferrer -- ? this.download.source.referrerInfo.originalReferrer.spec -- : null; -- -- let [displayHost] = DownloadUtils.getURIHost( -- referrer || this.download.source.url -- ); -+ let [displayHost] = DownloadUtils.getURIHost(this.download.source.url); - let [displayDate] = DownloadUtils.getReadableDates( - new Date(this.download.endTime) - ); diff --git a/CVE-2020-15678.patch b/CVE-2020-15678.patch deleted file mode 100644 index 185f4d9aa34e161dd65a3880ba6c29a6111901e3..0000000000000000000000000000000000000000 --- a/CVE-2020-15678.patch +++ /dev/null @@ -1,48 +0,0 @@ -# HG changeset patch -# User Botond Ballo -# Date 1598039821 0 -# Fri Aug 21 19:57:01 2020 +0000 -# Node ID 5718234b1f27780b0d98ca4e6f1a22e1b012205a -# Parent b6b562c539e326715fda1dcd020c1095a9520e93 -Bug 1660211 - Respect iterator invalidation rules in ComputeClippedCompositionBounds(). r=kats - -Differential Revision: https://phabricator.services.mozilla.com/D87893 - -diff -r b6b562c539e3 -r 5718234b1f27 gfx/layers/apz/src/APZCTreeManager.cpp ---- a/gfx/layers/apz/src/APZCTreeManager.cpp Fri Aug 21 20:42:59 2020 +0000 -+++ b/gfx/layers/apz/src/APZCTreeManager.cpp Fri Aug 21 19:57:01 2020 +0000 -@@ -899,14 +899,13 @@ - ParentLayerRect APZCTreeManager::ComputeClippedCompositionBounds( - const MutexAutoLock& aProofOfMapLock, ClippedCompositionBoundsMap& aDestMap, - ScrollableLayerGuid aGuid) { -- auto insertResult = aDestMap.insert(std::make_pair(aGuid, ParentLayerRect())); -- if (!insertResult.second) { -+ if (auto iter = aDestMap.find(aGuid); iter != aDestMap.end()) { - // We already computed it for this one, early-exit. This might happen - // because on a later iteration of mApzcMap we might encounter an ancestor - // of an APZC that we processed on an earlier iteration. In this case we - // would have computed the ancestor's clipped composition bounds when - // recursing up on the earlier iteration. -- return insertResult.first->second; -+ return iter->second; - } - - ParentLayerRect bounds = mApzcMap[aGuid].apzc->GetCompositionBounds(); -@@ -916,7 +915,7 @@ - // Recursion base case, where the APZC with guid `aGuid` has no parent. - // In this case, we don't need to clip `bounds` any further and can just - // early exit. -- insertResult.first->second = bounds; -+ aDestMap.emplace(aGuid, bounds); - return bounds; - } - -@@ -950,7 +949,7 @@ - PixelCastJustification::MovingDownToChildren)); - - // Done! -- insertResult.first->second = bounds; -+ aDestMap.emplace(aGuid, bounds); - return bounds; - } - diff --git a/CVE-2020-15969.patch b/CVE-2020-15969.patch deleted file mode 100644 index 9266f40053077cb3d4dc03629bd517be4166ad74..0000000000000000000000000000000000000000 --- a/CVE-2020-15969.patch +++ /dev/null @@ -1,51 +0,0 @@ -# HG changeset patch -# User Dan Minor -# Date 1600897949 0 -# Wed Sep 23 21:52:29 2020 +0000 -# Node ID ed2a659e965f27943d9b0c15d6e78d14e1ce9cb2 -# Parent 7b2de9e57a768d949b569ac83fe5d58147e731b5 -Bug 1666570 - Cherrypick ffed0925f27d404173c1e3e750d818f432d2c019 from usrsctp; r=drno - -Differential Revision: https://phabricator.services.mozilla.com/D91047 - -diff -r 7b2de9e57a76 -r ed2a659e965f netwerk/sctp/src/netinet/sctp_indata.c ---- a/netwerk/sctp/src/netinet/sctp_indata.c Wed Sep 23 19:42:19 2020 +0000 -+++ b/netwerk/sctp/src/netinet/sctp_indata.c Wed Sep 23 21:52:29 2020 +0000 -@@ -1664,6 +1664,7 @@ sctp_process_a_data_chunk(struct sctp_tc - /* Process a data chunk */ - /* struct sctp_tmit_chunk *chk; */ - struct sctp_tmit_chunk *chk; -+ struct sctp_stream_in *strm; - uint32_t tsn, fsn, gap, mid; - struct mbuf *dmbuf; - int the_len; -@@ -2296,12 +2297,13 @@ finish_express_del: - /* All can be removed */ - TAILQ_FOREACH_SAFE(control, &asoc->pending_reply_queue, next, ncontrol) { - TAILQ_REMOVE(&asoc->pending_reply_queue, control, next); -+ strm = &asoc->strmin[control->sinfo_stream]; - sctp_queue_data_to_stream(stcb, asoc, control, abort_flag, &need_reasm_check); - if (*abort_flag) { - return (0); - } - if (need_reasm_check) { -- (void)sctp_deliver_reasm_check(stcb, asoc, &asoc->strmin[control->sinfo_stream], SCTP_READ_LOCK_NOT_HELD); -+ (void)sctp_deliver_reasm_check(stcb, asoc, strm, SCTP_READ_LOCK_NOT_HELD); - need_reasm_check = 0; - } - } -@@ -2316,12 +2318,13 @@ finish_express_del: - * control->sinfo_tsn > liste->tsn - */ - TAILQ_REMOVE(&asoc->pending_reply_queue, control, next); -+ strm = &asoc->strmin[control->sinfo_stream]; - sctp_queue_data_to_stream(stcb, asoc, control, abort_flag, &need_reasm_check); - if (*abort_flag) { - return (0); - } - if (need_reasm_check) { -- (void)sctp_deliver_reasm_check(stcb, asoc, &asoc->strmin[control->sinfo_stream], SCTP_READ_LOCK_NOT_HELD); -+ (void)sctp_deliver_reasm_check(stcb, asoc, strm, SCTP_READ_LOCK_NOT_HELD); - need_reasm_check = 0; - } - } diff --git a/CVE-2020-15999.patch b/CVE-2020-15999.patch deleted file mode 100644 index 754bd385b52bcf234dbc169c1e02ca70d3d10635..0000000000000000000000000000000000000000 --- a/CVE-2020-15999.patch +++ /dev/null @@ -1,45 +0,0 @@ -# HG changeset patch -# User Werner Lemberg -# Date 1603223819 0 -# Tue Oct 20 19:56:59 2020 +0000 -# Node ID 5c356dd9b0f31f612ce90b1f35b14d8cdb0b4ecb -# Parent a2ed93bf78d53309eb234b72ce0bf60ad93a3ac3 -Bug 1672223 - [sfnt] Fix heap buffer overflow. r=jfkthame - -This is CVE-2020-15999. - -* src/sfnt/pngshim.c (Load_SBit_Png): Test bitmap size earlier. - -Differential Revision: https://phabricator.services.mozilla.com/D94153 - -diff -r a2ed93bf78d5 -r 5c356dd9b0f3 modules/freetype2/src/sfnt/pngshim.c ---- a/modules/freetype2/src/sfnt/pngshim.c Tue Oct 20 21:14:51 2020 +0000 -+++ b/modules/freetype2/src/sfnt/pngshim.c Tue Oct 20 19:56:59 2020 +0000 -@@ -328,6 +328,13 @@ - - if ( populate_map_and_metrics ) - { -+ /* reject too large bitmaps similarly to the rasterizer */ -+ if ( imgHeight > 0x7FFF || imgWidth > 0x7FFF ) -+ { -+ error = FT_THROW( Array_Too_Large ); -+ goto DestroyExit; -+ } -+ - metrics->width = (FT_UShort)imgWidth; - metrics->height = (FT_UShort)imgHeight; - -@@ -336,13 +343,6 @@ - map->pixel_mode = FT_PIXEL_MODE_BGRA; - map->pitch = (int)( map->width * 4 ); - map->num_grays = 256; -- -- /* reject too large bitmaps similarly to the rasterizer */ -- if ( map->rows > 0x7FFF || map->width > 0x7FFF ) -- { -- error = FT_THROW( Array_Too_Large ); -- goto DestroyExit; -- } - } - - /* convert palette/gray image to rgb */ diff --git a/CVE-2020-16012.patch b/CVE-2020-16012.patch deleted file mode 100644 index ba7ad9adacb6951b136674d4615d049f8531e6aa..0000000000000000000000000000000000000000 --- a/CVE-2020-16012.patch +++ /dev/null @@ -1,406 +0,0 @@ -# HG changeset patch -# User Lee Salzman -# Date 1601995009 0 -# Tue Oct 06 14:36:49 2020 +0000 -# Node ID 48c0f5033c286bd515b6f16e0905ff4ca94faf98 -# Parent 5bc02423412647e3ee9a0681b38e418a10901601 -Bug 1642028 - cherry-pick Skia blitting cleanups. r=jrmuizel - -Differential Revision: https://phabricator.services.mozilla.com/D92476 - -diff -r 5bc024234126 -r 48c0f5033c28 gfx/skia/skia/src/opts/SkBlitRow_opts.h ---- a/gfx/skia/skia/src/opts/SkBlitRow_opts.h Tue Oct 06 16:58:11 2020 +0000 -+++ b/gfx/skia/skia/src/opts/SkBlitRow_opts.h Tue Oct 06 14:36:49 2020 +0000 -@@ -58,37 +58,114 @@ - - return _mm256_add_epi32(src, _mm256_or_si256(rb, ga)); - } -+#endif - --#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 -+#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 - #include - - static inline __m128i SkPMSrcOver_SSE2(const __m128i& src, const __m128i& dst) { -- auto SkAlphaMulQ_SSE2 = [](const __m128i& c, const __m128i& scale) { -- const __m128i mask = _mm_set1_epi32(0xFF00FF); -- __m128i s = _mm_or_si128(_mm_slli_epi32(scale, 16), scale); -+ __m128i scale = _mm_sub_epi32(_mm_set1_epi32(256), -+ _mm_srli_epi32(src, 24)); -+ __m128i scale_x2 = _mm_or_si128(_mm_slli_epi32(scale, 16), scale); -+ -+ __m128i rb = _mm_and_si128(_mm_set1_epi32(0x00ff00ff), dst); -+ rb = _mm_mullo_epi16(rb, scale_x2); -+ rb = _mm_srli_epi16(rb, 8); - -- // uint32_t rb = ((c & mask) * scale) >> 8 -- __m128i rb = _mm_and_si128(mask, c); -- rb = _mm_mullo_epi16(rb, s); -- rb = _mm_srli_epi16(rb, 8); -+ __m128i ga = _mm_srli_epi16(dst, 8); -+ ga = _mm_mullo_epi16(ga, scale_x2); -+ ga = _mm_andnot_si128(_mm_set1_epi32(0x00ff00ff), ga); -+ -+ return _mm_add_epi32(src, _mm_or_si128(rb, ga)); -+ } -+#endif - -- // uint32_t ag = ((c >> 8) & mask) * scale -- __m128i ag = _mm_srli_epi16(c, 8); -- ag = _mm_mullo_epi16(ag, s); -- -- // (rb & mask) | (ag & ~mask) -- ag = _mm_andnot_si128(mask, ag); -- return _mm_or_si128(rb, ag); -+#if defined(SK_ARM_HAS_NEON) -+ #include -+ // SkMulDiv255Round() applied to each lane. -+ static inline uint8x8_t SkMulDiv255Round_neon8(uint8x8_t x, uint8x8_t y) { -+ uint16x8_t prod = vmull_u8(x, y); -+ return vraddhn_u16(prod, vrshrq_n_u16(prod, 8)); -+ } -+ static inline uint8x8x4_t SkPMSrcOver_neon8(uint8x8x4_t dst, uint8x8x4_t src) { -+ uint8x8_t nalphas = vmvn_u8(src.val[3]); // 256 - alpha -+ return { -+ vadd_u8(src.val[0], SkMulDiv255Round_neon8(nalphas, dst.val[0])), -+ vadd_u8(src.val[1], SkMulDiv255Round_neon8(nalphas, dst.val[1])), -+ vadd_u8(src.val[2], SkMulDiv255Round_neon8(nalphas, dst.val[2])), -+ vadd_u8(src.val[3], SkMulDiv255Round_neon8(nalphas, dst.val[3])), - }; -- return _mm_add_epi32(src, -- SkAlphaMulQ_SSE2(dst, _mm_sub_epi32(_mm_set1_epi32(256), -- _mm_srli_epi32(src, 24)))); -+ } -+ // Variant assuming dst and src contain the color components of two consecutive pixels. -+ static inline uint8x8_t SkPMSrcOver_neon2(uint8x8_t dst, uint8x8_t src) { -+ const uint8x8_t alpha_indices = vcreate_u8(0x0707070703030303); -+ uint8x8_t nalphas = vmvn_u8(vtbl1_u8(src, alpha_indices)); -+ return vadd_u8(src, SkMulDiv255Round_neon8(nalphas, dst)); - } - #endif - - namespace SK_OPTS_NS { - -+/*not static*/ -+inline void blit_row_s32a_opaque(SkPMColor* dst, const SkPMColor* src, int len, U8CPU alpha) { -+ SkASSERT(alpha == 0xFF); -+ sk_msan_assert_initialized(src, src+len); -+ -+#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2 -+ while (len >= 8) { -+ _mm256_storeu_si256((__m256i*)dst, -+ SkPMSrcOver_AVX2(_mm256_loadu_si256((const __m256i*)src), -+ _mm256_loadu_si256((const __m256i*)dst))); -+ src += 8; -+ dst += 8; -+ len -= 8; -+ } -+#endif -+ -+#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 -+ while (len >= 4) { -+ _mm_storeu_si128((__m128i*)dst, SkPMSrcOver_SSE2(_mm_loadu_si128((const __m128i*)src), -+ _mm_loadu_si128((const __m128i*)dst))); -+ src += 4; -+ dst += 4; -+ len -= 4; -+ } -+#endif -+ -+#if defined(SK_ARM_HAS_NEON) -+ while (len >= 8) { -+ vst4_u8((uint8_t*)dst, SkPMSrcOver_neon8(vld4_u8((const uint8_t*)dst), -+ vld4_u8((const uint8_t*)src))); -+ src += 8; -+ dst += 8; -+ len -= 8; -+ } -+ -+ while (len >= 2) { -+ vst1_u8((uint8_t*)dst, SkPMSrcOver_neon2(vld1_u8((const uint8_t*)dst), -+ vld1_u8((const uint8_t*)src))); -+ src += 2; -+ dst += 2; -+ len -= 2; -+ } -+ -+ if (len != 0) { -+ uint8x8_t result = SkPMSrcOver_neon2(vcreate_u8((uint64_t)*dst), -+ vcreate_u8((uint64_t)*src)); -+ vst1_lane_u32(dst, vreinterpret_u32_u8(result), 0); -+ } -+ return; -+#endif -+ -+ while (len --> 0) { -+ *dst = SkPMSrcOver(*src, *dst); -+ src++; -+ dst++; -+ } -+} -+ - // Blend constant color over count src pixels, writing into dst. -+/*not static*/ - inline void blit_row_color32(SkPMColor* dst, const SkPMColor* src, int count, SkPMColor color) { - constexpr int N = 4; // 8, 16 also reasonable choices - using U32 = skvx::Vec< N, uint32_t>; -@@ -120,259 +197,6 @@ - } - } - --#if defined(SK_ARM_HAS_NEON) -- --// Return a uint8x8_t value, r, computed as r[i] = SkMulDiv255Round(x[i], y[i]), where r[i], x[i], --// y[i] are the i-th lanes of the corresponding NEON vectors. --static inline uint8x8_t SkMulDiv255Round_neon8(uint8x8_t x, uint8x8_t y) { -- uint16x8_t prod = vmull_u8(x, y); -- return vraddhn_u16(prod, vrshrq_n_u16(prod, 8)); --} -- --// The implementations of SkPMSrcOver below perform alpha blending consistently with --// SkMulDiv255Round. They compute the color components (numbers in the interval [0, 255]) as: --// --// result_i = src_i + rint(g(src_alpha, dst_i)) --// --// where g(x, y) = ((255.0 - x) * y) / 255.0 and rint rounds to the nearest integer. -- --// In this variant of SkPMSrcOver each NEON register, dst.val[i], src.val[i], contains the value --// of the same color component for 8 consecutive pixels. The result of this function follows the --// same convention. --static inline uint8x8x4_t SkPMSrcOver_neon8(uint8x8x4_t dst, uint8x8x4_t src) { -- uint8x8_t nalphas = vmvn_u8(src.val[3]); -- uint8x8x4_t result; -- result.val[0] = vadd_u8(src.val[0], SkMulDiv255Round_neon8(nalphas, dst.val[0])); -- result.val[1] = vadd_u8(src.val[1], SkMulDiv255Round_neon8(nalphas, dst.val[1])); -- result.val[2] = vadd_u8(src.val[2], SkMulDiv255Round_neon8(nalphas, dst.val[2])); -- result.val[3] = vadd_u8(src.val[3], SkMulDiv255Round_neon8(nalphas, dst.val[3])); -- return result; --} -- --// In this variant of SkPMSrcOver dst and src contain the color components of two consecutive --// pixels. The return value follows the same convention. --static inline uint8x8_t SkPMSrcOver_neon2(uint8x8_t dst, uint8x8_t src) { -- const uint8x8_t alpha_indices = vcreate_u8(0x0707070703030303); -- uint8x8_t nalphas = vmvn_u8(vtbl1_u8(src, alpha_indices)); -- return vadd_u8(src, SkMulDiv255Round_neon8(nalphas, dst)); --} -- --#endif -- --/*not static*/ inline --void blit_row_s32a_opaque(SkPMColor* dst, const SkPMColor* src, int len, U8CPU alpha) { -- SkASSERT(alpha == 0xFF); -- sk_msan_assert_initialized(src, src+len); --// Require AVX2 because of AVX2 integer calculation intrinsics in SrcOver --#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2 -- while (len >= 32) { -- // Load 32 source pixels. -- auto s0 = _mm256_loadu_si256((const __m256i*)(src) + 0), -- s1 = _mm256_loadu_si256((const __m256i*)(src) + 1), -- s2 = _mm256_loadu_si256((const __m256i*)(src) + 2), -- s3 = _mm256_loadu_si256((const __m256i*)(src) + 3); -- -- const auto alphaMask = _mm256_set1_epi32(0xFF000000); -- -- auto ORed = _mm256_or_si256(s3, _mm256_or_si256(s2, _mm256_or_si256(s1, s0))); -- if (_mm256_testz_si256(ORed, alphaMask)) { -- // All 32 source pixels are transparent. Nothing to do. -- src += 32; -- dst += 32; -- len -= 32; -- continue; -- } -- -- auto d0 = (__m256i*)(dst) + 0, -- d1 = (__m256i*)(dst) + 1, -- d2 = (__m256i*)(dst) + 2, -- d3 = (__m256i*)(dst) + 3; -- -- auto ANDed = _mm256_and_si256(s3, _mm256_and_si256(s2, _mm256_and_si256(s1, s0))); -- if (_mm256_testc_si256(ANDed, alphaMask)) { -- // All 32 source pixels are opaque. SrcOver becomes Src. -- _mm256_storeu_si256(d0, s0); -- _mm256_storeu_si256(d1, s1); -- _mm256_storeu_si256(d2, s2); -- _mm256_storeu_si256(d3, s3); -- src += 32; -- dst += 32; -- len -= 32; -- continue; -- } -- -- // TODO: This math is wrong. -- // Do SrcOver. -- _mm256_storeu_si256(d0, SkPMSrcOver_AVX2(s0, _mm256_loadu_si256(d0))); -- _mm256_storeu_si256(d1, SkPMSrcOver_AVX2(s1, _mm256_loadu_si256(d1))); -- _mm256_storeu_si256(d2, SkPMSrcOver_AVX2(s2, _mm256_loadu_si256(d2))); -- _mm256_storeu_si256(d3, SkPMSrcOver_AVX2(s3, _mm256_loadu_si256(d3))); -- src += 32; -- dst += 32; -- len -= 32; -- } -- --#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41 -- while (len >= 16) { -- // Load 16 source pixels. -- auto s0 = _mm_loadu_si128((const __m128i*)(src) + 0), -- s1 = _mm_loadu_si128((const __m128i*)(src) + 1), -- s2 = _mm_loadu_si128((const __m128i*)(src) + 2), -- s3 = _mm_loadu_si128((const __m128i*)(src) + 3); -- -- const auto alphaMask = _mm_set1_epi32(0xFF000000); -- -- auto ORed = _mm_or_si128(s3, _mm_or_si128(s2, _mm_or_si128(s1, s0))); -- if (_mm_testz_si128(ORed, alphaMask)) { -- // All 16 source pixels are transparent. Nothing to do. -- src += 16; -- dst += 16; -- len -= 16; -- continue; -- } -- -- auto d0 = (__m128i*)(dst) + 0, -- d1 = (__m128i*)(dst) + 1, -- d2 = (__m128i*)(dst) + 2, -- d3 = (__m128i*)(dst) + 3; -- -- auto ANDed = _mm_and_si128(s3, _mm_and_si128(s2, _mm_and_si128(s1, s0))); -- if (_mm_testc_si128(ANDed, alphaMask)) { -- // All 16 source pixels are opaque. SrcOver becomes Src. -- _mm_storeu_si128(d0, s0); -- _mm_storeu_si128(d1, s1); -- _mm_storeu_si128(d2, s2); -- _mm_storeu_si128(d3, s3); -- src += 16; -- dst += 16; -- len -= 16; -- continue; -- } -- -- // TODO: This math is wrong. -- // Do SrcOver. -- _mm_storeu_si128(d0, SkPMSrcOver_SSE2(s0, _mm_loadu_si128(d0))); -- _mm_storeu_si128(d1, SkPMSrcOver_SSE2(s1, _mm_loadu_si128(d1))); -- _mm_storeu_si128(d2, SkPMSrcOver_SSE2(s2, _mm_loadu_si128(d2))); -- _mm_storeu_si128(d3, SkPMSrcOver_SSE2(s3, _mm_loadu_si128(d3))); -- src += 16; -- dst += 16; -- len -= 16; -- } -- --#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 -- while (len >= 16) { -- // Load 16 source pixels. -- auto s0 = _mm_loadu_si128((const __m128i*)(src) + 0), -- s1 = _mm_loadu_si128((const __m128i*)(src) + 1), -- s2 = _mm_loadu_si128((const __m128i*)(src) + 2), -- s3 = _mm_loadu_si128((const __m128i*)(src) + 3); -- -- const auto alphaMask = _mm_set1_epi32(0xFF000000); -- -- auto ORed = _mm_or_si128(s3, _mm_or_si128(s2, _mm_or_si128(s1, s0))); -- if (0xffff == _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_and_si128(ORed, alphaMask), -- _mm_setzero_si128()))) { -- // All 16 source pixels are transparent. Nothing to do. -- src += 16; -- dst += 16; -- len -= 16; -- continue; -- } -- -- auto d0 = (__m128i*)(dst) + 0, -- d1 = (__m128i*)(dst) + 1, -- d2 = (__m128i*)(dst) + 2, -- d3 = (__m128i*)(dst) + 3; -- -- auto ANDed = _mm_and_si128(s3, _mm_and_si128(s2, _mm_and_si128(s1, s0))); -- if (0xffff == _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_and_si128(ANDed, alphaMask), -- alphaMask))) { -- // All 16 source pixels are opaque. SrcOver becomes Src. -- _mm_storeu_si128(d0, s0); -- _mm_storeu_si128(d1, s1); -- _mm_storeu_si128(d2, s2); -- _mm_storeu_si128(d3, s3); -- src += 16; -- dst += 16; -- len -= 16; -- continue; -- } -- -- // TODO: This math is wrong. -- // Do SrcOver. -- _mm_storeu_si128(d0, SkPMSrcOver_SSE2(s0, _mm_loadu_si128(d0))); -- _mm_storeu_si128(d1, SkPMSrcOver_SSE2(s1, _mm_loadu_si128(d1))); -- _mm_storeu_si128(d2, SkPMSrcOver_SSE2(s2, _mm_loadu_si128(d2))); -- _mm_storeu_si128(d3, SkPMSrcOver_SSE2(s3, _mm_loadu_si128(d3))); -- -- src += 16; -- dst += 16; -- len -= 16; -- } -- --#elif defined(SK_ARM_HAS_NEON) -- // Do 8-pixels at a time. A 16-pixels at a time version of this code was also tested, but it -- // underperformed on some of the platforms under test for inputs with frequent transitions of -- // alpha (corresponding to changes of the conditions [~]alpha_u64 == 0 below). It may be worth -- // revisiting the situation in the future. -- while (len >= 8) { -- // Load 8 pixels in 4 NEON registers. src_col.val[i] will contain the same color component -- // for 8 consecutive pixels (e.g. src_col.val[3] will contain all alpha components of 8 -- // pixels). -- uint8x8x4_t src_col = vld4_u8(reinterpret_cast(src)); -- src += 8; -- len -= 8; -- -- // We now detect 2 special cases: the first occurs when all alphas are zero (the 8 pixels -- // are all transparent), the second when all alphas are fully set (they are all opaque). -- uint8x8_t alphas = src_col.val[3]; -- uint64_t alphas_u64 = vget_lane_u64(vreinterpret_u64_u8(alphas), 0); -- if (alphas_u64 == 0) { -- // All pixels transparent. -- dst += 8; -- continue; -- } -- -- if (~alphas_u64 == 0) { -- // All pixels opaque. -- vst4_u8(reinterpret_cast(dst), src_col); -- dst += 8; -- continue; -- } -- -- uint8x8x4_t dst_col = vld4_u8(reinterpret_cast(dst)); -- vst4_u8(reinterpret_cast(dst), SkPMSrcOver_neon8(dst_col, src_col)); -- dst += 8; -- } -- -- // Deal with leftover pixels. -- for (; len >= 2; len -= 2, src += 2, dst += 2) { -- uint8x8_t src2 = vld1_u8(reinterpret_cast(src)); -- uint8x8_t dst2 = vld1_u8(reinterpret_cast(dst)); -- vst1_u8(reinterpret_cast(dst), SkPMSrcOver_neon2(dst2, src2)); -- } -- -- if (len != 0) { -- uint8x8_t result = SkPMSrcOver_neon2(vcreate_u8(*dst), vcreate_u8(*src)); -- vst1_lane_u32(dst, vreinterpret_u32_u8(result), 0); -- } -- return; --#endif -- -- while (len-- > 0) { -- // This 0xFF000000 is not semantically necessary, but for compatibility -- // with chromium:611002 we need to keep it until we figure out where -- // the non-premultiplied src values (like 0x00FFFFFF) are coming from. -- // TODO(mtklein): sort this out and assert *src is premul here. -- if (*src & 0xFF000000) { -- *dst = (*src >= 0xFF000000) ? *src : SkPMSrcOver(*src, *dst); -- } -- src++; -- dst++; -- } --} -- - } // SK_OPTS_NS - - #endif//SkBlitRow_opts_DEFINED diff --git a/CVE-2020-26951-1.patch b/CVE-2020-26951-1.patch deleted file mode 100644 index ccfbcb5c19aa613f1bbd1559cb9ff55d1a995c21..0000000000000000000000000000000000000000 --- a/CVE-2020-26951-1.patch +++ /dev/null @@ -1,102 +0,0 @@ -# HG changeset patch -# User Henri Sivonen -# Date 1603457336 0 -# Fri Oct 23 12:48:56 2020 +0000 -# Node ID 9143f95d5ab3896f5461fa1666500f6fc1f9e73b -# Parent b067b0d3670b37daad95505b87bddca6bb113d11 -Bug 1667113. r=smaug - -Differential Revision: https://phabricator.services.mozilla.com/D93482 - -diff -r b067b0d3670b -r 9143f95d5ab3 browser/base/content/test/static/browser_parsable_css.js ---- a/browser/base/content/test/static/browser_parsable_css.js Fri Oct 23 12:48:52 2020 +0000 -+++ b/browser/base/content/test/static/browser_parsable_css.js Fri Oct 23 12:48:56 2020 +0000 -@@ -496,9 +496,9 @@ - checkWhitelist(propNameWhitelist); - - // Clean up to avoid leaks: -- iframe.remove(); - doc.head.innerHTML = ""; - doc = null; -+ iframe.remove(); - iframe = null; - win = null; - hiddenFrame.destroy(); -diff -r b067b0d3670b -r 9143f95d5ab3 dom/base/nsContentUtils.cpp ---- a/dom/base/nsContentUtils.cpp Fri Oct 23 12:48:52 2020 +0000 -+++ b/dom/base/nsContentUtils.cpp Fri Oct 23 12:48:56 2020 +0000 -@@ -4817,6 +4817,7 @@ - - nsIContent* target = aTargetNode; - -+ RefPtr inert; - RefPtr fragment; - // We sanitize if the fragment occurs in a system privileged - // context, an about: page, or if there are explicit sanitization flags. -@@ -4828,8 +4828,12 @@ - nodePrincipal->SchemeIs("about") || aFlags >= 0; - if (shouldSanitize) { - if (!AllowsUnsanitizedContentForAboutNewTab(nodePrincipal)) { -- fragment = new (aTargetNode->OwnerDoc()->NodeInfoManager()) -- DocumentFragment(aTargetNode->OwnerDoc()->NodeInfoManager()); -+ inert = nsContentUtils::CreateInertHTMLDocument(aTargetNode->OwnerDoc()); -+ if (!inert) { -+ return NS_ERROR_FAILURE; -+ } -+ fragment = new (inert->NodeInfoManager()) -+ DocumentFragment(inert->NodeInfoManager()); - target = fragment; - } - } -@@ -4908,22 +4908,7 @@ - MOZ_ASSERT(contentsink, "Sink doesn't QI to nsIContentSink!"); - sXMLFragmentParser->SetContentSink(contentsink); - -- sXMLFragmentSink->SetTargetDocument(aDocument); -- sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution); -- -- nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack); -- if (NS_FAILED(rv)) { -- // Drop the fragment parser and sink that might be in an inconsistent state -- NS_IF_RELEASE(sXMLFragmentParser); -- NS_IF_RELEASE(sXMLFragmentSink); -- return rv; -- } -- -- rv = sXMLFragmentSink->FinishFragmentParsing(aReturn); -- -- sXMLFragmentParser->Reset(); -- NS_ENSURE_SUCCESS(rv, rv); -- -+ RefPtr doc; - nsCOMPtr nodePrincipal = aDocument->NodePrincipal(); - - #ifdef DEBUG -@@ -4929,6 +4929,27 @@ - // an about: scheme principal. - bool shouldSanitize = nodePrincipal->IsSystemPrincipal() || - nodePrincipal->SchemeIs("about") || aFlags >= 0; -+ if (shouldSanitize) { -+ doc = nsContentUtils::CreateInertXMLDocument(aDocument); -+ } else { -+ doc = aDocument; -+ } -+ -+ sXMLFragmentSink->SetTargetDocument(doc); -+ sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution); -+ -+ nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack); -+ if (NS_FAILED(rv)) { -+ // Drop the fragment parser and sink that might be in an inconsistent state -+ NS_IF_RELEASE(sXMLFragmentParser); -+ NS_IF_RELEASE(sXMLFragmentSink); -+ return rv; -+ } -+ -+ rv = sXMLFragmentSink->FinishFragmentParsing(aReturn); -+ -+ sXMLFragmentParser->Reset(); -+ NS_ENSURE_SUCCESS(rv, rv); - - if (shouldSanitize) { - uint32_t sanitizationFlags = diff --git a/CVE-2020-26951-2.patch b/CVE-2020-26951-2.patch deleted file mode 100644 index 89a4c489ec7070743f48094373f1337a7da4f1a7..0000000000000000000000000000000000000000 --- a/CVE-2020-26951-2.patch +++ /dev/null @@ -1,177 +0,0 @@ -# HG changeset patch -# User Henri Sivonen -# Date 1605719930 0 -# Wed Nov 18 17:18:50 2020 +0000 -# Node ID 027514ba89006dfd5c346c307e46ed8f79e358c1 -# Parent 782446e715644da3ca8226d0c3413e3fafb69d6f -Bug 1667113 test - Test innerHTML sanitizer in chrome context. r=smaug - -Differential Revision: https://phabricator.services.mozilla.com/D93928 - -diff -r 782446e71564 -r 027514ba8900 dom/security/test/general/chrome.ini ---- a/dom/security/test/general/chrome.ini Wed Nov 18 17:18:56 2020 +0000 -+++ b/dom/security/test/general/chrome.ini Wed Nov 18 17:18:50 2020 +0000 -@@ -3,6 +3,8 @@ - favicon_bug1277803.ico - bug1277803.html - -+[test_innerhtml_sanitizer.html] -+[test_innerhtml_sanitizer.xhtml] - [test_bug1277803.xhtml] - skip-if = os == 'android' || verify - -diff -r 782446e71564 -r 027514ba8900 dom/security/test/general/test_innerhtml_sanitizer.html ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/dom/security/test/general/test_innerhtml_sanitizer.html Wed Nov 18 17:18:50 2020 +0000 -@@ -0,0 +1,74 @@ -+ -+ -+ -+ -+ Test for Bug 1667113 -+ -+ -+ -+ -+Mozilla Bug 1667113 -+
-+ -+ -+ -diff -r 782446e71564 -r 027514ba8900 dom/security/test/general/test_innerhtml_sanitizer.xhtml ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/dom/security/test/general/test_innerhtml_sanitizer.xhtml Wed Nov 18 17:18:50 2020 +0000 -@@ -0,0 +1,73 @@ -+ -+ -+ -+ Test for Bug 1667113 -+ -+ -+ -+ -+Mozilla Bug 1667113 -+
-+ -+ -+ diff --git a/CVE-2020-26953-pre.patch b/CVE-2020-26953-pre.patch deleted file mode 100644 index f7cd27b2cbc5a2b6c3b9876af46520e719e01692..0000000000000000000000000000000000000000 --- a/CVE-2020-26953-pre.patch +++ /dev/null @@ -1,85 +0,0 @@ -# HG changeset patch -# User Alphan Chen -# Date 1593745253 0 -# Fri Jul 03 03:00:53 2020 +0000 -# Node ID aff172a1f77244bf24cfccc966c917bf801b5cbd -# Parent d69131a21feedc02c202912955ae015c74c4c8ec -Bug 1644484 - Handle the TypeError and InvalidStateError when calling FullScreen.cleanupDomFullscreen() from DOMFullscreenParent.didDestroy() r=Gijs - -Differential Revision: https://phabricator.services.mozilla.com/D81716 - -diff -r d69131a21fee -r aff172a1f772 browser/base/content/browser-fullScreenAndPointerLock.js ---- a/browser/base/content/browser-fullScreenAndPointerLock.js Fri Jul 03 01:30:12 2020 +0000 -+++ b/browser/base/content/browser-fullScreenAndPointerLock.js Fri Jul 03 03:00:53 2020 +0000 -@@ -345,7 +345,9 @@ - }, - - exitDomFullScreen() { -- document.exitFullscreen(); -+ if (document.fullscreen) { -+ document.exitFullscreen(); -+ } - }, - - handleEvent(event) { -@@ -508,8 +510,15 @@ - - /** - * Search for the first ancestor of aActor that lives in a different process. -- * If found, that ancestor is sent the message. Otherwise, the recipient should -- * be the actor of the request origin. -+ * If found, that ancestor is sent the message and return false. -+ * Otherwise, the recipient should be the actor of the request origin and return true -+ * from this function. -+ * -+ * The method will be called again as a result of targeted child process doing -+ * "FullScreen.enterDomFullscreen()" or "FullScreen.cleanupDomFullscreen()". -+ * The return value is used to postpone entering or exiting Full Screen in the parent -+ * until there is no ancestor anymore. -+ * - * - * @param {JSWindowActorParent} aActor - * The actor that called this function. -@@ -517,6 +526,10 @@ - * Message to be sent. - * - * @return {boolean} -+ * The return value is used to postpone entering or exiting Full Screen in the -+ * parent until there is no ancestor anymore. -+ * Return false if the message is send to the first ancestor of aActor that -+ * lives in a different process - * Return true if the message is sent to the request source - * or false otherwise. - */ -@@ -530,6 +543,9 @@ - let parentBC = childBC.parent; - - while (parentBC) { -+ if (!childBC.currentWindowGlobal || !parentBC.currentWindowGlobal) { -+ break; -+ } - let childPid = childBC.currentWindowGlobal.osPid; - let parentPid = parentBC.currentWindowGlobal.osPid; - -@@ -541,7 +557,7 @@ - } - } - -- if (parentBC) { -+ if (parentBC && parentBC.currentWindowGlobal) { - let parentActor = parentBC.currentWindowGlobal.getActor("DOMFullscreen"); - parentActor.sendAsyncMessage(aMessage, { - remoteFrameBC: childBC, -@@ -554,8 +570,10 @@ - // have entered or exited fullscreen at this point. - // So let's notify the process where the original request - // comes from. -- aActor.requestOrigin.sendAsyncMessage(aMessage, {}); -- aActor.requestOrigin = null; -+ if (!aActor.requestOrigin.hasBeenDestroyed()) { -+ aActor.requestOrigin.sendAsyncMessage(aMessage, {}); -+ aActor.requestOrigin = null; -+ } - return true; - }, - diff --git a/CVE-2020-26953.patch b/CVE-2020-26953.patch deleted file mode 100644 index 4d171ae9c55a81f49f5608667b72de06025003f8..0000000000000000000000000000000000000000 --- a/CVE-2020-26953.patch +++ /dev/null @@ -1,231 +0,0 @@ -# HG changeset patch -# User Steven MacLeod -# Date 1601937483 0 -# Mon Oct 05 22:38:03 2020 +0000 -# Node ID 3e884c48633fb4017402ef2c7053f8d947676dd5 -# Parent b4b7e943b93cdc77a479bd5484f7661985bdb7d4 -Bug 1656741, r=Gijs - -Differential Revision: https://phabricator.services.mozilla.com/D91760 - -diff -r b4b7e943b93c -r 3e884c48633f browser/actors/DOMFullscreenParent.jsm ---- a/browser/actors/DOMFullscreenParent.jsm Mon Oct 05 22:20:41 2020 +0000 -+++ b/browser/actors/DOMFullscreenParent.jsm Mon Oct 05 22:38:03 2020 +0000 -@@ -9,6 +9,8 @@ - const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); - - class DOMFullscreenParent extends JSWindowActorParent { -+ waitingForChildFullscreen = false; -+ - updateFullscreenWindowReference(aWindow) { - if (aWindow.document.documentElement.hasAttribute("inDOMFullscreen")) { - this._fullscreenWindow = aWindow; -@@ -23,6 +25,20 @@ - return; - } - -+ if (this.waitingForChildFullscreen) { -+ // We were killed while waiting for our DOMFullscreenChild -+ // to transition to fullscreen so we abort the entire -+ // fullscreen transition to prevent getting stuck in a -+ // partial fullscreen state. We need to go through the -+ // document since window.Fullscreen could be undefined -+ // at this point. -+ // -+ // This could reject if we're not currently in fullscreen -+ // so just ignore rejection. -+ window.document.exitFullscreen().catch(() => {}); -+ return; -+ } -+ - // Need to resume Chrome UI if the window is still in fullscreen UI - // to avoid the window stays in fullscreen problem. (See Bug 1620341) - if (window.document.documentElement.hasAttribute("inDOMFullscreen")) { -@@ -64,6 +80,7 @@ - break; - } - case "DOMFullscreen:Entered": { -+ this.waitingForChildFullscreen = false; - window.FullScreen.enterDomFullscreen(browser, this); - this.updateFullscreenWindowReference(window); - break; -diff -r b4b7e943b93c -r 3e884c48633f browser/base/content/browser-fullScreenAndPointerLock.js ---- a/browser/base/content/browser-fullScreenAndPointerLock.js Mon Oct 05 22:20:41 2020 +0000 -+++ b/browser/base/content/browser-fullScreenAndPointerLock.js Mon Oct 05 22:38:03 2020 +0000 -@@ -420,12 +420,27 @@ - // before the check is fine since we also check the activeness of - // the requesting document in content-side handling code. - if (this._isRemoteBrowser(aBrowser)) { -- if ( -- !this._sendMessageToTheRightContent(aActor, "DOMFullscreen:Entered") -- ) { -+ let [targetActor, inProcessBC] = this._getNextMsgRecipientActor(aActor); -+ if (!targetActor) { -+ // If there is no appropriate actor to send the message we have -+ // no way to complete the transition and should abort by exiting -+ // fullscreen. -+ this._abortEnterFullscreen(); -+ return; -+ } -+ targetActor.sendAsyncMessage("DOMFullscreen:Entered", { -+ remoteFrameBC: inProcessBC, -+ }); -+ -+ // Record that the actor is waiting for its child to enter -+ // fullscreen so that if it dies we can abort. -+ targetActor.waitingForChildFullscreen = true; -+ if (inProcessBC) { -+ // We aren't messaging the request origin yet, skip this time. - return; - } - } -+ - // If we've received a fullscreen notification, we have to ensure that the - // element that's requesting fullscreen belongs to the browser that's currently - // active. If not, we exit fullscreen since the "full-screen document" isn't -@@ -437,9 +452,7 @@ - // full-screen was made. Cancel full-screen. - Services.focus.activeWindow != window - ) { -- // This function is called synchronously in fullscreen change, so -- // we have to avoid calling exitFullscreen synchronously here. -- setTimeout(() => document.exitFullscreen(), 0); -+ this._abortEnterFullscreen(); - return; - } - -@@ -453,7 +466,6 @@ - this._logWarningPermissionPromptFS("promptCanceled"); - } - } -- - document.documentElement.setAttribute("inDOMFullscreen", true); - - if (gFindBarInitialized) { -@@ -488,9 +500,25 @@ - } - }, - -+ /** -+ * Clean up full screen, starting from the request origin's first ancestor -+ * frame that is OOP. -+ * -+ * If there are OOP ancestor frames, we notify the first of those and then bail to -+ * be called again in that process when it has dealt with the change. This is -+ * repeated until all ancestor processes have been updated. Once that has happened -+ * we remove our handlers and attributes and notify the request origin to complete -+ * the cleanup. -+ */ - cleanupDomFullscreen(aActor) { -- if (!this._sendMessageToTheRightContent(aActor, "DOMFullscreen:CleanUp")) { -- return; -+ let [target, inProcessBC] = this._getNextMsgRecipientActor(aActor); -+ if (target) { -+ target.sendAsyncMessage("DOMFullscreen:CleanUp", { -+ remoteFrameBC: inProcessBC, -+ }); -+ if (inProcessBC) { -+ return; -+ } - } - - PopupNotifications.panel.removeEventListener( -@@ -508,40 +536,43 @@ - document.documentElement.removeAttribute("inDOMFullscreen"); - }, - -+ _abortEnterFullscreen() { -+ // This function is called synchronously in fullscreen change, so -+ // we have to avoid calling exitFullscreen synchronously here. -+ setTimeout(() => document.exitFullscreen(), 0); -+ if (TelemetryStopwatch.running("FULLSCREEN_CHANGE_MS")) { -+ // Cancel the stopwatch for any fullscreen change to avoid -+ // errors if it is started again. -+ TelemetryStopwatch.cancel("FULLSCREEN_CHANGE_MS"); -+ } -+ }, -+ - /** - * Search for the first ancestor of aActor that lives in a different process. -- * If found, that ancestor is sent the message and return false. -- * Otherwise, the recipient should be the actor of the request origin and return true -- * from this function. -- * -- * The method will be called again as a result of targeted child process doing -- * "FullScreen.enterDomFullscreen()" or "FullScreen.cleanupDomFullscreen()". -- * The return value is used to postpone entering or exiting Full Screen in the parent -- * until there is no ancestor anymore. -+ * If found, that ancestor actor and the browsing context for its child which -+ * was in process are returned. Otherwise [request origin, null]. - * - * - * @param {JSWindowActorParent} aActor - * The actor that called this function. -- * @param {String} message -- * Message to be sent. - * -- * @return {boolean} -- * The return value is used to postpone entering or exiting Full Screen in the -- * parent until there is no ancestor anymore. -- * Return false if the message is send to the first ancestor of aActor that -- * lives in a different process -- * Return true if the message is sent to the request source -- * or false otherwise. -+ * @return {[JSWindowActorParent, BrowsingContext]} -+ * The parent actor which should be sent the next msg and the -+ * in process browsing context which is its child. Will be -+ * [null, null] if there is no OOP parent actor and request origin -+ * is unset. [null, null] is also returned if the intended actor or -+ * the calling actor has been destroyed. - */ -- _sendMessageToTheRightContent(aActor, aMessage) { -+ _getNextMsgRecipientActor(aActor) { - if (aActor.hasBeenDestroyed()) { -- // Just restore the chrome UI when the actor is dead. -- return true; -+ return [null, null]; - } - - let childBC = aActor.browsingContext; - let parentBC = childBC.parent; - -+ // Walk up the browsing context tree from aActor's browsing context -+ // to find the first ancestor browsing context that's in a different process. - while (parentBC) { - if (!childBC.currentWindowGlobal || !parentBC.currentWindowGlobal) { - break; -@@ -557,24 +588,20 @@ - } - } - -+ let target = null; -+ let inProcessBC = null; -+ - if (parentBC && parentBC.currentWindowGlobal) { -- let parentActor = parentBC.currentWindowGlobal.getActor("DOMFullscreen"); -- parentActor.sendAsyncMessage(aMessage, { -- remoteFrameBC: childBC, -- }); -- return false; -+ target = parentBC.currentWindowGlobal.getActor("DOMFullscreen"); -+ inProcessBC = childBC; -+ } else { -+ target = aActor.requestOrigin; - } - -- // All content frames living outside the process where -- // the element requesting fullscreen lives should -- // have entered or exited fullscreen at this point. -- // So let's notify the process where the original request -- // comes from. -- if (!aActor.requestOrigin.hasBeenDestroyed()) { -- aActor.requestOrigin.sendAsyncMessage(aMessage, {}); -- aActor.requestOrigin = null; -+ if (!target || target.hasBeenDestroyed()) { -+ return [null, null]; - } -- return true; -+ return [target, inProcessBC]; - }, - - _isRemoteBrowser(aBrowser) { diff --git a/CVE-2020-26956-1.patch b/CVE-2020-26956-1.patch deleted file mode 100644 index e88427e8aadfb773c0beea6c3d4ea41ac9d5abe5..0000000000000000000000000000000000000000 --- a/CVE-2020-26956-1.patch +++ /dev/null @@ -1,56 +0,0 @@ -# HG changeset patch -# User Henri Sivonen -# Date 1603457329 0 -# Fri Oct 23 12:48:49 2020 +0000 -# Node ID 3476387362fb15c82f133f390afef719ad36de0a -# Parent fd45fcfd6261e9ed6cf83e54ad8286717f1b4762 -Bug 1666300 part 1 - Remove attributes from descendants when setting sanitized style. r=smaug - -Differential Revision: https://phabricator.services.mozilla.com/D93215 - -diff -r fd45fcfd6261 -r 3476387362fb dom/base/nsTreeSanitizer.cpp ---- a/dom/base/nsTreeSanitizer.cpp Fri Oct 23 13:04:19 2020 +0000 -+++ b/dom/base/nsTreeSanitizer.cpp Fri Oct 23 12:48:49 2020 +0000 -@@ -1341,6 +1341,7 @@ - nsAutoString sanitizedStyle; - SanitizeStyleSheet(styleText, sanitizedStyle, aRoot->OwnerDoc(), - node->GetBaseURI()); -+ RemoveAllAttributesFromDescendants(elt); - nsContentUtils::SetNodeTextContent(node, sanitizedStyle, true); - - if (!mOnlyConditionalCSS) { -@@ -1427,6 +1428,18 @@ - } - } - -+void nsTreeSanitizer::RemoveAllAttributesFromDescendants( -+ mozilla::dom::Element* aElement) { -+ nsIContent* node = aElement->GetFirstChild(); -+ while (node) { -+ if (node->IsElement()) { -+ mozilla::dom::Element* elt = node->AsElement(); -+ RemoveAllAttributes(elt); -+ } -+ node = node->GetNextNode(aElement); -+ } -+} -+ - void nsTreeSanitizer::LogMessage(const char* aMessage, Document* aDoc, - Element* aElement, nsAtom* aAttr) { - if (mLogRemovals) { -diff -r fd45fcfd6261 -r 3476387362fb dom/base/nsTreeSanitizer.h ---- a/dom/base/nsTreeSanitizer.h Fri Oct 23 13:04:19 2020 +0000 -+++ b/dom/base/nsTreeSanitizer.h Fri Oct 23 12:48:49 2020 +0000 -@@ -200,6 +200,12 @@ - void RemoveAllAttributes(mozilla::dom::Element* aElement); - - /** -+ * Removes all attributes from the descendants of an element but not from -+ * the element itself. -+ */ -+ void RemoveAllAttributesFromDescendants(mozilla::dom::Element* aElement); -+ -+ /** - * Log a Console Service message to indicate we removed something. - * If you pass an element and/or attribute, their information will - * be appended to the message. diff --git a/CVE-2020-26956-2.patch b/CVE-2020-26956-2.patch deleted file mode 100644 index 639e796dc0c74b75e8b4aa37b3b3162a405d4e40..0000000000000000000000000000000000000000 --- a/CVE-2020-26956-2.patch +++ /dev/null @@ -1,171 +0,0 @@ -# HG changeset patch -# User Henri Sivonen -# Date 1603457332 0 -# Fri Oct 23 12:48:52 2020 +0000 -# Node ID b067b0d3670b37daad95505b87bddca6bb113d11 -# Parent 3476387362fb15c82f133f390afef719ad36de0a -Bug 1666300 part 2 - Parse into an inert document. r=smaug - -Differential Revision: https://phabricator.services.mozilla.com/D93478 - -diff -r 3476387362fb -r b067b0d3670b dom/base/nsContentUtils.cpp ---- a/dom/base/nsContentUtils.cpp Fri Oct 23 12:48:49 2020 +0000 -+++ b/dom/base/nsContentUtils.cpp Fri Oct 23 12:48:52 2020 +0000 -@@ -4968,17 +4968,12 @@ - nsAString& aResultBuffer, - uint32_t aFlags, - uint32_t aWrapCol) { -- nsCOMPtr uri; -- NS_NewURI(getter_AddRefs(uri), "about:blank"); -- nsCOMPtr principal = -- NullPrincipal::CreateWithoutOriginAttributes(); -- RefPtr document; -- nsresult rv = NS_NewDOMDocument(getter_AddRefs(document), EmptyString(), -- EmptyString(), nullptr, uri, uri, principal, -- true, nullptr, DocumentFlavorHTML); -- NS_ENSURE_SUCCESS(rv, rv); -- -- rv = nsContentUtils::ParseDocumentHTML( -+ RefPtr document = nsContentUtils::CreateInertHTMLDocument(nullptr); -+ if (!document) { -+ return NS_ERROR_FAILURE; -+ } -+ -+ nsresult rv = nsContentUtils::ParseDocumentHTML( - aSourceBuffer, document, - !(aFlags & nsIDocumentEncoder::OutputNoScriptContent)); - NS_ENSURE_SUCCESS(rv, rv); -@@ -4994,6 +4989,58 @@ - } - - /* static */ -+already_AddRefed nsContentUtils::CreateInertXMLDocument( -+ const Document* aTemplate) { -+ return nsContentUtils::CreateInertDocument(aTemplate, DocumentFlavorXML); -+} -+ -+/* static */ -+already_AddRefed nsContentUtils::CreateInertHTMLDocument( -+ const Document* aTemplate) { -+ return nsContentUtils::CreateInertDocument(aTemplate, DocumentFlavorHTML); -+} -+ -+/* static */ -+already_AddRefed nsContentUtils::CreateInertDocument( -+ const Document* aTemplate, DocumentFlavor aFlavor) { -+ if (aTemplate) { -+ bool hasHad = true; -+ nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad); -+ NS_ENSURE_TRUE(sgo || !hasHad, nullptr); -+ -+ nsCOMPtr doc; -+ nsresult rv = NS_NewDOMDocument( -+ getter_AddRefs(doc), NS_LITERAL_STRING(""), NS_LITERAL_STRING(""), nullptr, -+ aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(), -+ aTemplate->NodePrincipal(), true, sgo, aFlavor); -+ if (NS_FAILED(rv)) { -+ return nullptr; -+ } -+ return doc.forget(); -+ } -+ nsCOMPtr uri; -+ NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank")); -+ if (!uri) { -+ return nullptr; -+ } -+ -+ RefPtr nullPrincipal = -+ NullPrincipal::CreateWithoutOriginAttributes(); -+ if (!nullPrincipal) { -+ return nullptr; -+ } -+ -+ nsCOMPtr doc; -+ nsresult rv = -+ NS_NewDOMDocument(getter_AddRefs(doc), NS_LITERAL_STRING(""), NS_LITERAL_STRING(""), nullptr, uri, uri, -+ nullPrincipal, true, nullptr, aFlavor); -+ if (NS_FAILED(rv)) { -+ return nullptr; -+ } -+ return doc.forget(); -+} -+ -+/* static */ - nsresult nsContentUtils::SetNodeTextContent(nsIContent* aContent, - const nsAString& aValue, - bool aTryReuse) { -diff -r 3476387362fb -r b067b0d3670b dom/base/nsContentUtils.h ---- a/dom/base/nsContentUtils.h Fri Oct 23 12:48:49 2020 +0000 -+++ b/dom/base/nsContentUtils.h Fri Oct 23 12:48:52 2020 +0000 -@@ -1831,6 +1831,25 @@ - uint32_t aWrapCol); - - /** -+ * Creates a 'loaded-as-data' HTML document that takes that principal, -+ * script global, and URL from the argument, which may be null. -+ */ -+ static already_AddRefed CreateInertHTMLDocument( -+ const Document* aTemplate); -+ -+ /** -+ * Creates a 'loaded-as-data' XML document that takes that principal, -+ * script global, and URL from the argument, which may be null. -+ */ -+ static already_AddRefed CreateInertXMLDocument( -+ const Document* aTemplate); -+ -+ private: -+ static already_AddRefed CreateInertDocument( -+ const Document* aTemplate, DocumentFlavor aFlavor); -+ -+ public: -+ /** - * Sets the text contents of a node by replacing all existing children - * with a single text child. - * -diff -r 3476387362fb -r b067b0d3670b editor/libeditor/HTMLEditorDataTransfer.cpp ---- a/editor/libeditor/HTMLEditorDataTransfer.cpp Fri Oct 23 12:48:49 2020 +0000 -+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp Fri Oct 23 12:48:52 2020 +0000 -@@ -3039,8 +3039,13 @@ - bool aTrustedInput) { - nsAutoScriptBlockerSuppressNodeRemoved autoBlocker; - -- RefPtr fragment = new (aTargetDocument->NodeInfoManager()) -- DocumentFragment(aTargetDocument->NodeInfoManager()); -+ nsCOMPtr doc = -+ nsContentUtils::CreateInertHTMLDocument(aTargetDocument); -+ if (!doc) { -+ return NS_ERROR_FAILURE; -+ } -+ RefPtr fragment = -+ new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager()); - nsresult rv = nsContentUtils::ParseFragmentHTML( - aFragStr, fragment, - aContextLocalName ? aContextLocalName : nsGkAtoms::body, -diff -r 3476387362fb -r b067b0d3670b parser/html/nsParserUtils.cpp ---- a/parser/html/nsParserUtils.cpp Fri Oct 23 12:48:49 2020 +0000 -+++ b/parser/html/nsParserUtils.cpp Fri Oct 23 12:48:52 2020 +0000 -@@ -45,17 +45,13 @@ - NS_IMETHODIMP - nsParserUtils::Sanitize(const nsAString& aFromStr, uint32_t aFlags, - nsAString& aToStr) { -- nsCOMPtr uri; -- NS_NewURI(getter_AddRefs(uri), "about:blank"); -- nsCOMPtr principal = -- mozilla::NullPrincipal::CreateWithoutOriginAttributes(); -- RefPtr document; -- nsresult rv = NS_NewDOMDocument(getter_AddRefs(document), EmptyString(), -- EmptyString(), nullptr, uri, uri, principal, -- true, nullptr, DocumentFlavorHTML); -- NS_ENSURE_SUCCESS(rv, rv); -+ RefPtr document = nsContentUtils::CreateInertHTMLDocument(nullptr); - -- rv = nsContentUtils::ParseDocumentHTML(aFromStr, document, false); -+ if (!document) { -+ return NS_ERROR_FAILURE; -+ } -+ -+ nsresult rv = nsContentUtils::ParseDocumentHTML(aFromStr, document, false); - NS_ENSURE_SUCCESS(rv, rv); - - nsTreeSanitizer sanitizer(aFlags); diff --git a/CVE-2020-26956-3.patch b/CVE-2020-26956-3.patch deleted file mode 100644 index 82c44124e4566841301b7c863fab9003d8b55c99..0000000000000000000000000000000000000000 --- a/CVE-2020-26956-3.patch +++ /dev/null @@ -1,99 +0,0 @@ -# HG changeset patch -# User Henri Sivonen -# Date 1605719936 0 -# Wed Nov 18 17:18:56 2020 +0000 -# Node ID 782446e715644da3ca8226d0c3413e3fafb69d6f -# Parent 42be1816b3857a3962cd0ec4be551830b6639aee -Bug 1666300 test - Test SVG style sanitization on paste. r=smaug - -Differential Revision: https://phabricator.services.mozilla.com/D93634 - -diff -r 42be1816b385 -r 782446e71564 editor/libeditor/tests/file_sanitizer_on_paste.sjs ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/editor/libeditor/tests/file_sanitizer_on_paste.sjs Wed Nov 18 17:18:56 2020 +0000 -@@ -0,0 +1,16 @@ -+function handleRequest(request, response) -+{ -+ if (request.queryString.indexOf("report") != -1) { -+ response.setHeader("Content-Type", "text/javascript", false); -+ if (getState("loaded") == "loaded") { -+ response.write("ok(false, 'There was an attempt to preload the image.');"); -+ } else { -+ response.write("ok(true, 'There was no attempt to preload the image.');"); -+ } -+ response.write("SimpleTest.finish();"); -+ } else { -+ setState("loaded", "loaded"); -+ response.setHeader("Content-Type", "image/svg", false); -+ response.write("Not supposed to load this"); -+ } -+} -diff -r 42be1816b385 -r 782446e71564 editor/libeditor/tests/mochitest.ini ---- a/editor/libeditor/tests/mochitest.ini Wed Dec 16 10:40:06 2020 +0200 -+++ b/editor/libeditor/tests/mochitest.ini Wed Nov 18 17:18:56 2020 +0000 -@@ -21,6 +21,7 @@ - file_bug966155.html - file_bug966552.html - file_select_all_without_body.html -+ file_sanitizer_on_paste.sjs - green.png - spellcheck.js - -@@ -305,3 +306,4 @@ - [test_selection_move_commands.html] - [test_pasteImgTextarea.html] - [test_execCommandPaste_noTarget.html] -+[test_sanitizer_on_paste.html] -diff -r 42be1816b385 -r 782446e71564 editor/libeditor/tests/test_sanitizer_on_paste.html ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/editor/libeditor/tests/test_sanitizer_on_paste.html Wed Nov 18 17:18:56 2020 +0000 -@@ -0,0 +1,48 @@ -+ -+ -+ -+ -+ Test pasting table rows -+ -+ -+ -+ -+ -+ -+
Paste target
-+ -+ -\ No newline at end of file diff --git a/CVE-2020-26957.patch b/CVE-2020-26957.patch deleted file mode 100644 index 59a2fb1c406c58b1942780f3aaf896e1bf64ca02..0000000000000000000000000000000000000000 --- a/CVE-2020-26957.patch +++ /dev/null @@ -1,33 +0,0 @@ -# HG changeset patch -# User Agi Sferro -# Date 1602608252 0 -# Tue Oct 13 16:57:32 2020 +0000 -# Node ID 1aa2dc4b280e4ac1d5d5742e1923d5d39c04c102 -# Parent 943130e5f28ed6ee3e6b8bbf0f9c9f60fb5a7053 -Bug 1667179 - Initialize OneCRL when GeckoView starts. r=snorp,jcj - -Differential Revision: https://phabricator.services.mozilla.com/D93250 - -diff -r 943130e5f28e -r 1aa2dc4b280e mobile/android/chrome/geckoview/geckoview.js ---- a/mobile/android/chrome/geckoview/geckoview.js Tue Oct 13 16:59:30 2020 +0000 -+++ b/mobile/android/chrome/geckoview/geckoview.js Tue Oct 13 16:57:32 2020 +0000 -@@ -18,6 +18,8 @@ - GeckoViewSettings: "resource://gre/modules/GeckoViewSettings.jsm", - GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm", - HistogramStopwatch: "resource://gre/modules/GeckoViewTelemetry.jsm", -+ RemoteSecuritySettings: -+ "resource://gre/modules/psm/RemoteSecuritySettings.jsm", - }); - - XPCOMUtils.defineLazyGetter(this, "WindowEventDispatcher", () => -@@ -610,6 +612,10 @@ - Services.obs.notifyObservers(window, "extensions-late-startup"); - }); - -+ InitLater(() => { -+ RemoteSecuritySettings.init(); -+ }); -+ - // This should always go last, since the idle tasks (except for the ones with - // timeouts) should execute in order. Note that this observer notification is - // not guaranteed to fire, since the window could close before we get here. diff --git a/CVE-2020-26958.patch b/CVE-2020-26958.patch deleted file mode 100644 index c99ce0474573b78b9f9adf5036d600d0f8782dc6..0000000000000000000000000000000000000000 --- a/CVE-2020-26958.patch +++ /dev/null @@ -1,768 +0,0 @@ -# HG changeset patch -# User Andrew Sutherland -# Date 1603887323 0 -# Wed Oct 28 12:15:23 2020 +0000 -# Node ID 6873589e0ede3c11bc48243be67c3d51e214873f -# Parent e6a1286e25b70d36a1e251fb056596181565d839 -Bug 1669355 - Refactor MIME type warnings into base class. r=necko-reviewers,valentin - -Differential Revision: https://phabricator.services.mozilla.com/D93906 - -diff -r e6a1286e25b7 -r 6873589e0ede netwerk/protocol/http/HttpBaseChannel.cpp ---- a/netwerk/protocol/http/HttpBaseChannel.cpp 2020-07-21 06:49:41.000000000 +0800 -+++ b/netwerk/protocol/http/HttpBaseChannel.cpp 2021-01-06 11:26:44.608483314 +0800 -@@ -24,10 +24,12 @@ - #include "mozilla/NullPrincipal.h" - #include "mozilla/Services.h" - #include "mozilla/StaticPrefs_browser.h" -+#include "mozilla/StaticPrefs_security.h" - #include "mozilla/Telemetry.h" - #include "mozilla/Tokenizer.h" - #include "mozilla/dom/BrowsingContext.h" - #include "mozilla/dom/CanonicalBrowsingContext.h" -+#include "mozilla/dom/Document.h" - #include "mozilla/dom/Performance.h" - #include "mozilla/dom/PerformanceStorage.h" - #include "mozilla/dom/WindowGlobalParent.h" -@@ -2385,6 +2387,354 @@ nsresult HttpBaseChannel::ComputeCrossOr - return NS_OK; - } - -+enum class Report { Error, Warning }; -+ -+// Helper Function to report messages to the console when the loaded -+// script had a wrong MIME type. -+void ReportMimeTypeMismatch(HttpBaseChannel* aChannel, const char* aMessageName, -+ nsIURI* aURI, const nsACString& aContentType, -+ Report report) { -+ NS_ConvertUTF8toUTF16 spec(aURI->GetSpecOrDefault()); -+ NS_ConvertUTF8toUTF16 contentType(aContentType); -+ -+ aChannel->LogMimeTypeMismatch(nsCString(aMessageName), -+ report == Report::Warning, spec, contentType); -+} -+ -+// Check and potentially enforce X-Content-Type-Options: nosniff -+nsresult ProcessXCTO(HttpBaseChannel* aChannel, nsIURI* aURI, -+ nsHttpResponseHead* aResponseHead, -+ nsILoadInfo* aLoadInfo) { -+ if (!aURI || !aResponseHead || !aLoadInfo) { -+ // if there is no uri, no response head or no loadInfo, then there is -+ // nothing to do -+ return NS_OK; -+ } -+ -+ // 1) Query the XCTO header and check if 'nosniff' is the first value. -+ nsAutoCString contentTypeOptionsHeader; -+ if (!aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader)) { -+ // if failed to get XCTO header, then there is nothing to do. -+ return NS_OK; -+ } -+ -+ // let's compare the header (ignoring case) -+ // e.g. "NoSniFF" -> "nosniff" -+ // if it's not 'nosniff' then there is nothing to do here -+ if (!contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) { -+ // since we are getting here, the XCTO header was sent; -+ // a non matching value most likely means a mistake happenend; -+ // e.g. sending 'nosnif' instead of 'nosniff', let's log a warning. -+ AutoTArray params; -+ CopyUTF8toUTF16(contentTypeOptionsHeader, *params.AppendElement()); -+ RefPtr doc; -+ aLoadInfo->GetLoadingDocument(getter_AddRefs(doc)); -+ nsContentUtils::ReportToConsole( -+ nsIScriptError::warningFlag, NS_LITERAL_CSTRING("XCTO"), doc, -+ nsContentUtils::eSECURITY_PROPERTIES, "XCTOHeaderValueMissing", params); -+ return NS_OK; -+ } -+ -+ // 2) Query the content type from the channel -+ nsAutoCString contentType; -+ aResponseHead->ContentType(contentType); -+ -+ // 3) Compare the expected MIME type with the actual type -+ if (aLoadInfo->GetExternalContentPolicyType() == -+ nsIContentPolicy::TYPE_STYLESHEET) { -+ if (contentType.EqualsLiteral(TEXT_CSS)) { -+ return NS_OK; -+ } -+ ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType, -+ Report::Error); -+ return NS_ERROR_CORRUPTED_CONTENT; -+ } -+ -+ if (aLoadInfo->GetExternalContentPolicyType() == -+ nsIContentPolicy::TYPE_SCRIPT) { -+ if (nsContentUtils::IsJavascriptMIMEType( -+ NS_ConvertUTF8toUTF16(contentType))) { -+ return NS_OK; -+ } -+ ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType, -+ Report::Error); -+ return NS_ERROR_CORRUPTED_CONTENT; -+ } -+ -+ auto policyType = aLoadInfo->GetExternalContentPolicyType(); -+ if ((policyType == nsIContentPolicy::TYPE_DOCUMENT || -+ policyType == nsIContentPolicy::TYPE_SUBDOCUMENT) && -+ gHttpHandler->IsDocumentNosniffEnabled()) { -+ // If the header XCTO nosniff is set for any browsing context, then -+ // we set the skipContentSniffing flag on the Loadinfo. Within -+ // GetMIMETypeFromContent we then bail early and do not do any sniffing. -+ aLoadInfo->SetSkipContentSniffing(true); -+ return NS_OK; -+ } -+ -+ return NS_OK; -+} -+ -+// Ensure that a load of type script has correct MIME type -+nsresult EnsureMIMEOfScript(HttpBaseChannel* aChannel, nsIURI* aURI, -+ nsHttpResponseHead* aResponseHead, -+ nsILoadInfo* aLoadInfo) { -+ if (!aURI || !aResponseHead || !aLoadInfo) { -+ // if there is no uri, no response head or no loadInfo, then there is -+ // nothing to do -+ return NS_OK; -+ } -+ -+ if (aLoadInfo->GetExternalContentPolicyType() != -+ nsIContentPolicy::TYPE_SCRIPT) { -+ // if this is not a script load, then there is nothing to do -+ return NS_OK; -+ } -+ -+ nsAutoCString contentType; -+ aResponseHead->ContentType(contentType); -+ NS_ConvertUTF8toUTF16 typeString(contentType); -+ -+ if (nsContentUtils::IsJavascriptMIMEType(typeString)) { -+ // script load has type script -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::javaScript); -+ return NS_OK; -+ } -+ -+ switch (aLoadInfo->InternalContentPolicyType()) { -+ case nsIContentPolicy::TYPE_SCRIPT: -+ case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: -+ case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: -+ case nsIContentPolicy::TYPE_INTERNAL_MODULE: -+ case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD: -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::script_load); -+ break; -+ case nsIContentPolicy::TYPE_INTERNAL_WORKER: -+ case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::worker_load); -+ break; -+ case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::serviceworker_load); -+ break; -+ case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS: -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::importScript_load); -+ break; -+ case nsIContentPolicy::TYPE_INTERNAL_AUDIOWORKLET: -+ case nsIContentPolicy::TYPE_INTERNAL_PAINTWORKLET: -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::worklet_load); -+ break; -+ default: -+ MOZ_ASSERT_UNREACHABLE("unexpected script type"); -+ break; -+ } -+ -+ bool isPrivateWin = aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; -+ bool isSameOrigin = false; -+ aLoadInfo->GetLoadingPrincipal()->IsSameOrigin(aURI, isPrivateWin, -+ &isSameOrigin); -+ if (isSameOrigin) { -+ // same origin -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::same_origin); -+ } else { -+ bool cors = false; -+ nsAutoCString corsOrigin; -+ nsresult rv = aResponseHead->GetHeader( -+ nsHttp::ResolveAtom("Access-Control-Allow-Origin"), corsOrigin); -+ if (NS_SUCCEEDED(rv)) { -+ if (corsOrigin.Equals("*")) { -+ cors = true; -+ } else { -+ nsCOMPtr corsOriginURI; -+ rv = NS_NewURI(getter_AddRefs(corsOriginURI), corsOrigin); -+ if (NS_SUCCEEDED(rv)) { -+ bool isPrivateWin = -+ aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; -+ bool isSameOrigin = false; -+ aLoadInfo->GetLoadingPrincipal()->IsSameOrigin( -+ corsOriginURI, isPrivateWin, &isSameOrigin); -+ if (isSameOrigin) { -+ cors = true; -+ } -+ } -+ } -+ } -+ if (cors) { -+ // cors origin -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::CORS_origin); -+ } else { -+ // cross origin -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::cross_origin); -+ } -+ } -+ -+ bool block = false; -+ if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/"))) { -+ // script load has type image -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::image); -+ block = true; -+ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("audio/"))) { -+ // script load has type audio -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::audio); -+ block = true; -+ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("video/"))) { -+ // script load has type video -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::video); -+ block = true; -+ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/csv"))) { -+ // script load has type text/csv -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_csv); -+ block = true; -+ } -+ -+ if (block) { -+ // Do not block the load if the feature is not enabled. -+ if (!StaticPrefs::security_block_script_with_wrong_mime()) { -+ return NS_OK; -+ } -+ -+ ReportMimeTypeMismatch(aChannel, "BlockScriptWithWrongMimeType2", aURI, -+ contentType, Report::Error); -+ return NS_ERROR_CORRUPTED_CONTENT; -+ } -+ -+ if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/plain"))) { -+ // script load has type text/plain -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_plain); -+ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/xml"))) { -+ // script load has type text/xml -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_xml); -+ } else if (StringBeginsWith(contentType, -+ NS_LITERAL_CSTRING("application/octet-stream"))) { -+ // script load has type application/octet-stream -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_octet_stream); -+ } else if (StringBeginsWith(contentType, -+ NS_LITERAL_CSTRING("application/xml"))) { -+ // script load has type application/xml -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_xml); -+ } else if (StringBeginsWith(contentType, -+ NS_LITERAL_CSTRING("application/json"))) { -+ // script load has type application/json -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_json); -+ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/json"))) { -+ // script load has type text/json -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_json); -+ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/html"))) { -+ // script load has type text/html -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_html); -+ } else if (contentType.IsEmpty()) { -+ // script load has no type -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::empty); -+ } else { -+ // script load has unknown type -+ AccumulateCategorical( -+ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::unknown); -+ } -+ -+ // We restrict importScripts() in worker code to JavaScript MIME types. -+ nsContentPolicyType internalType = aLoadInfo->InternalContentPolicyType(); -+ if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS) { -+ // Do not block the load if the feature is not enabled. -+ if (!StaticPrefs::security_block_importScripts_with_wrong_mime()) { -+ return NS_OK; -+ } -+ -+ ReportMimeTypeMismatch(aChannel, "BlockImportScriptsWithWrongMimeType", -+ aURI, contentType, Report::Error); -+ return NS_ERROR_CORRUPTED_CONTENT; -+ } -+ -+ if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER || -+ internalType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER) { -+ // Do not block the load if the feature is not enabled. -+ if (!StaticPrefs::security_block_Worker_with_wrong_mime()) { -+ return NS_OK; -+ } -+ -+ ReportMimeTypeMismatch(aChannel, "BlockWorkerWithWrongMimeType", aURI, -+ contentType, Report::Error); -+ return NS_ERROR_CORRUPTED_CONTENT; -+ } -+ -+ // ES6 modules require a strict MIME type check. -+ if (internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE || -+ internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD) { -+ ReportMimeTypeMismatch(aChannel, "BlockModuleWithWrongMimeType", aURI, -+ contentType, Report::Error); -+ return NS_ERROR_CORRUPTED_CONTENT; -+ } -+ -+ return NS_OK; -+} -+ -+// Warn when a load of type script uses a wrong MIME type and -+// wasn't blocked by EnsureMIMEOfScript or ProcessXCTO. -+void WarnWrongMIMEOfScript(HttpBaseChannel* aChannel, nsIURI* aURI, -+ nsHttpResponseHead* aResponseHead, -+ nsILoadInfo* aLoadInfo) { -+ if (!aURI || !aResponseHead || !aLoadInfo) { -+ // If there is no uri, no response head or no loadInfo, then there is -+ // nothing to do. -+ return; -+ } -+ -+ if (aLoadInfo->GetExternalContentPolicyType() != -+ nsIContentPolicy::TYPE_SCRIPT) { -+ // If this is not a script load, then there is nothing to do. -+ return; -+ } -+ -+ bool succeeded; -+ MOZ_ALWAYS_SUCCEEDS(aChannel->GetRequestSucceeded(&succeeded)); -+ if (!succeeded) { -+ // Do not warn for failed loads: HTTP error pages are usually in HTML. -+ return; -+ } -+ -+ nsAutoCString contentType; -+ aResponseHead->ContentType(contentType); -+ NS_ConvertUTF8toUTF16 typeString(contentType); -+ if (!nsContentUtils::IsJavascriptMIMEType(typeString)) { -+ ReportMimeTypeMismatch(aChannel, "WarnScriptWithWrongMimeType", aURI, -+ contentType, Report::Warning); -+ } -+} -+ -+nsresult HttpBaseChannel::ValidateMIMEType() { -+ nsresult rv = EnsureMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo); -+ if (NS_FAILED(rv)) { -+ return rv; -+ } -+ -+ rv = ProcessXCTO(this, mURI, mResponseHead.get(), mLoadInfo); -+ if (NS_FAILED(rv)) { -+ return rv; -+ } -+ -+ WarnWrongMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo); -+ return NS_OK; -+} -+ - NS_IMETHODIMP - HttpBaseChannel::SetCookie(const nsACString& aCookieHeader) { - if (mLoadFlags & LOAD_ANONYMOUS) return NS_OK; -diff -r e6a1286e25b7 -r 6873589e0ede netwerk/protocol/http/HttpBaseChannel.h ---- a/netwerk/protocol/http/HttpBaseChannel.h 2020-07-21 04:53:32.000000000 +0800 -+++ b/netwerk/protocol/http/HttpBaseChannel.h 2021-01-06 10:53:17.326264473 +0800 -@@ -610,6 +610,8 @@ class HttpBaseChannel : public nsHashPro - - nsresult ComputeCrossOriginOpenerPolicyMismatch(); - -+ nsresult ValidateMIMEType(); -+ - friend class PrivateBrowsingChannel; - friend class InterceptFailedOnStop; - -diff -r e6a1286e25b7 -r 6873589e0ede netwerk/protocol/http/InterceptedHttpChannel.cpp ---- a/netwerk/protocol/http/InterceptedHttpChannel.cpp 2020-07-21 06:49:41.000000000 +0800 -+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp 2021-01-06 10:53:17.326264473 +0800 -@@ -1046,6 +1046,12 @@ InterceptedHttpChannel::OnStartRequest(n - Cancel(mStatus); - } - -+ rv = ValidateMIMEType(); -+ if (NS_FAILED(rv)) { -+ mStatus = rv; -+ Cancel(mStatus); -+ } -+ - mOnStartRequestCalled = true; - if (mListener) { - return mListener->OnStartRequest(this); -diff -r e6a1286e25b7 -r 6873589e0ede netwerk/protocol/http/nsHttpChannel.cpp ---- a/netwerk/protocol/http/nsHttpChannel.cpp 2021-01-06 10:53:17.330264533 +0800 -+++ b/netwerk/protocol/http/nsHttpChannel.cpp 2021-01-06 11:10:19.257650688 +0800 -@@ -1485,339 +1485,6 @@ HttpTrafficCategory nsHttpChannel::Creat - NS_UsePrivateBrowsing(this), isSystemPrincipal, isThirdParty, cos, tc); - } - --enum class Report { Error, Warning }; -- --// Helper Function to report messages to the console when the loaded --// script had a wrong MIME type. --void ReportMimeTypeMismatch(nsHttpChannel* aChannel, const char* aMessageName, -- nsIURI* aURI, const nsACString& aContentType, -- Report report) { -- NS_ConvertUTF8toUTF16 spec(aURI->GetSpecOrDefault()); -- NS_ConvertUTF8toUTF16 contentType(aContentType); -- -- aChannel->LogMimeTypeMismatch(nsCString(aMessageName), -- report == Report::Warning, spec, contentType); --} -- --// Check and potentially enforce X-Content-Type-Options: nosniff --nsresult ProcessXCTO(nsHttpChannel* aChannel, nsIURI* aURI, -- nsHttpResponseHead* aResponseHead, -- nsILoadInfo* aLoadInfo) { -- if (!aURI || !aResponseHead || !aLoadInfo) { -- // if there is no uri, no response head or no loadInfo, then there is -- // nothing to do -- return NS_OK; -- } -- -- // 1) Query the XCTO header and check if 'nosniff' is the first value. -- nsAutoCString contentTypeOptionsHeader; -- if (!aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader)) { -- // if failed to get XCTO header, then there is nothing to do. -- return NS_OK; -- } -- -- // let's compare the header (ignoring case) -- // e.g. "NoSniFF" -> "nosniff" -- // if it's not 'nosniff' then there is nothing to do here -- if (!contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) { -- // since we are getting here, the XCTO header was sent; -- // a non matching value most likely means a mistake happenend; -- // e.g. sending 'nosnif' instead of 'nosniff', let's log a warning. -- AutoTArray params; -- CopyUTF8toUTF16(contentTypeOptionsHeader, *params.AppendElement()); -- RefPtr doc; -- aLoadInfo->GetLoadingDocument(getter_AddRefs(doc)); -- nsContentUtils::ReportToConsole( -- nsIScriptError::warningFlag, NS_LITERAL_CSTRING("XCTO"), doc, -- nsContentUtils::eSECURITY_PROPERTIES, "XCTOHeaderValueMissing", params); -- return NS_OK; -- } -- -- // 2) Query the content type from the channel -- nsAutoCString contentType; -- aResponseHead->ContentType(contentType); -- -- // 3) Compare the expected MIME type with the actual type -- if (aLoadInfo->GetExternalContentPolicyType() == -- nsIContentPolicy::TYPE_STYLESHEET) { -- if (contentType.EqualsLiteral(TEXT_CSS)) { -- return NS_OK; -- } -- ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType, -- Report::Error); -- return NS_ERROR_CORRUPTED_CONTENT; -- } -- -- if (aLoadInfo->GetExternalContentPolicyType() == -- nsIContentPolicy::TYPE_SCRIPT) { -- if (nsContentUtils::IsJavascriptMIMEType( -- NS_ConvertUTF8toUTF16(contentType))) { -- return NS_OK; -- } -- ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType, -- Report::Error); -- return NS_ERROR_CORRUPTED_CONTENT; -- } -- -- auto policyType = aLoadInfo->GetExternalContentPolicyType(); -- if ((policyType == nsIContentPolicy::TYPE_DOCUMENT || -- policyType == nsIContentPolicy::TYPE_SUBDOCUMENT) && -- gHttpHandler->IsDocumentNosniffEnabled()) { -- // If the header XCTO nosniff is set for any browsing context, then -- // we set the skipContentSniffing flag on the Loadinfo. Within -- // GetMIMETypeFromContent we then bail early and do not do any sniffing. -- aLoadInfo->SetSkipContentSniffing(true); -- return NS_OK; -- } -- -- return NS_OK; --} -- --// Ensure that a load of type script has correct MIME type --nsresult EnsureMIMEOfScript(nsHttpChannel* aChannel, nsIURI* aURI, -- nsHttpResponseHead* aResponseHead, -- nsILoadInfo* aLoadInfo) { -- if (!aURI || !aResponseHead || !aLoadInfo) { -- // if there is no uri, no response head or no loadInfo, then there is -- // nothing to do -- return NS_OK; -- } -- -- if (aLoadInfo->GetExternalContentPolicyType() != -- nsIContentPolicy::TYPE_SCRIPT) { -- // if this is not a script load, then there is nothing to do -- return NS_OK; -- } -- -- nsAutoCString contentType; -- aResponseHead->ContentType(contentType); -- NS_ConvertUTF8toUTF16 typeString(contentType); -- -- if (nsContentUtils::IsJavascriptMIMEType(typeString)) { -- // script load has type script -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::javaScript); -- return NS_OK; -- } -- -- switch (aLoadInfo->InternalContentPolicyType()) { -- case nsIContentPolicy::TYPE_SCRIPT: -- case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: -- case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: -- case nsIContentPolicy::TYPE_INTERNAL_MODULE: -- case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD: -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::script_load); -- break; -- case nsIContentPolicy::TYPE_INTERNAL_WORKER: -- case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::worker_load); -- break; -- case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::serviceworker_load); -- break; -- case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS: -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::importScript_load); -- break; -- case nsIContentPolicy::TYPE_INTERNAL_AUDIOWORKLET: -- case nsIContentPolicy::TYPE_INTERNAL_PAINTWORKLET: -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::worklet_load); -- break; -- default: -- MOZ_ASSERT_UNREACHABLE("unexpected script type"); -- break; -- } -- -- bool isPrivateWin = aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; -- bool isSameOrigin = false; -- aLoadInfo->GetLoadingPrincipal()->IsSameOrigin(aURI, isPrivateWin, -- &isSameOrigin); -- if (isSameOrigin) { -- // same origin -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::same_origin); -- } else { -- bool cors = false; -- nsAutoCString corsOrigin; -- nsresult rv = aResponseHead->GetHeader( -- nsHttp::ResolveAtom("Access-Control-Allow-Origin"), corsOrigin); -- if (NS_SUCCEEDED(rv)) { -- if (corsOrigin.Equals("*")) { -- cors = true; -- } else { -- nsCOMPtr corsOriginURI; -- rv = NS_NewURI(getter_AddRefs(corsOriginURI), corsOrigin); -- if (NS_SUCCEEDED(rv)) { -- bool isPrivateWin = -- aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; -- bool isSameOrigin = false; -- aLoadInfo->GetLoadingPrincipal()->IsSameOrigin( -- corsOriginURI, isPrivateWin, &isSameOrigin); -- if (isSameOrigin) { -- cors = true; -- } -- } -- } -- } -- if (cors) { -- // cors origin -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::CORS_origin); -- } else { -- // cross origin -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::cross_origin); -- } -- } -- -- bool block = false; -- if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/"))) { -- // script load has type image -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::image); -- block = true; -- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("audio/"))) { -- // script load has type audio -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::audio); -- block = true; -- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("video/"))) { -- // script load has type video -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::video); -- block = true; -- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/csv"))) { -- // script load has type text/csv -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_csv); -- block = true; -- } -- -- if (block) { -- // Do not block the load if the feature is not enabled. -- if (!StaticPrefs::security_block_script_with_wrong_mime()) { -- return NS_OK; -- } -- -- ReportMimeTypeMismatch(aChannel, "BlockScriptWithWrongMimeType2", aURI, -- contentType, Report::Error); -- return NS_ERROR_CORRUPTED_CONTENT; -- } -- -- if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/plain"))) { -- // script load has type text/plain -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_plain); -- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/xml"))) { -- // script load has type text/xml -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_xml); -- } else if (StringBeginsWith(contentType, -- NS_LITERAL_CSTRING("application/octet-stream"))) { -- // script load has type application/octet-stream -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_octet_stream); -- } else if (StringBeginsWith(contentType, -- NS_LITERAL_CSTRING("application/xml"))) { -- // script load has type application/xml -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_xml); -- } else if (StringBeginsWith(contentType, -- NS_LITERAL_CSTRING("application/json"))) { -- // script load has type application/json -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_json); -- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/json"))) { -- // script load has type text/json -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_json); -- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/html"))) { -- // script load has type text/html -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_html); -- } else if (contentType.IsEmpty()) { -- // script load has no type -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::empty); -- } else { -- // script load has unknown type -- AccumulateCategorical( -- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::unknown); -- } -- -- // We restrict importScripts() in worker code to JavaScript MIME types. -- nsContentPolicyType internalType = aLoadInfo->InternalContentPolicyType(); -- if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS) { -- // Do not block the load if the feature is not enabled. -- if (!StaticPrefs::security_block_importScripts_with_wrong_mime()) { -- return NS_OK; -- } -- -- ReportMimeTypeMismatch(aChannel, "BlockImportScriptsWithWrongMimeType", -- aURI, contentType, Report::Error); -- return NS_ERROR_CORRUPTED_CONTENT; -- } -- -- if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER || -- internalType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER) { -- // Do not block the load if the feature is not enabled. -- if (!StaticPrefs::security_block_Worker_with_wrong_mime()) { -- return NS_OK; -- } -- -- ReportMimeTypeMismatch(aChannel, "BlockWorkerWithWrongMimeType", aURI, -- contentType, Report::Error); -- return NS_ERROR_CORRUPTED_CONTENT; -- } -- -- // ES6 modules require a strict MIME type check. -- if (internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE || -- internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD) { -- ReportMimeTypeMismatch(aChannel, "BlockModuleWithWrongMimeType", aURI, -- contentType, Report::Error); -- return NS_ERROR_CORRUPTED_CONTENT; -- } -- -- return NS_OK; --} -- --// Warn when a load of type script uses a wrong MIME type and --// wasn't blocked by EnsureMIMEOfScript or ProcessXCTO. --void WarnWrongMIMEOfScript(nsHttpChannel* aChannel, nsIURI* aURI, -- nsHttpResponseHead* aResponseHead, -- nsILoadInfo* aLoadInfo) { -- if (!aURI || !aResponseHead || !aLoadInfo) { -- // If there is no uri, no response head or no loadInfo, then there is -- // nothing to do. -- return; -- } -- -- if (aLoadInfo->GetExternalContentPolicyType() != -- nsIContentPolicy::TYPE_SCRIPT) { -- // If this is not a script load, then there is nothing to do. -- return; -- } -- -- bool succeeded; -- MOZ_ALWAYS_SUCCEEDS(aChannel->GetRequestSucceeded(&succeeded)); -- if (!succeeded) { -- // Do not warn for failed loads: HTTP error pages are usually in HTML. -- return; -- } -- -- nsAutoCString contentType; -- aResponseHead->ContentType(contentType); -- NS_ConvertUTF8toUTF16 typeString(contentType); -- if (!nsContentUtils::IsJavascriptMIMEType(typeString)) { -- ReportMimeTypeMismatch(aChannel, "WarnScriptWithWrongMimeType", aURI, -- contentType, Report::Warning); -- } --} -- - void nsHttpChannel::SetCachedContentType() { - if (!mResponseHead) { - return; -@@ -1913,14 +1580,9 @@ nsresult nsHttpChannel::CallOnStartReque - mOnStartRequestCalled = true; - }); - -- nsresult rv = EnsureMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo); -- NS_ENSURE_SUCCESS(rv, rv); -- -- rv = ProcessXCTO(this, mURI, mResponseHead.get(), mLoadInfo); -+ nsresult rv = ValidateMIMEType(); - NS_ENSURE_SUCCESS(rv, rv); - -- WarnWrongMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo); -- - // Allow consumers to override our content type - if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) { - // NOTE: We can have both a txn pump and a cache pump when the cache diff --git a/CVE-2020-26959.patch b/CVE-2020-26959.patch deleted file mode 100644 index a1d612f0135863d5ae6deb82b29e0ef09250486b..0000000000000000000000000000000000000000 --- a/CVE-2020-26959.patch +++ /dev/null @@ -1,63 +0,0 @@ -# HG changeset patch -# User Luca Greco -# Date 1603810809 0 -# Tue Oct 27 15:00:09 2020 +0000 -# Node ID 8de8cd3371e801d408650f102df04252c846f33d -# Parent 5058a78c1008f0917866aa09abff7430bcefa085 -Bug 1669466 - Change WebRequestService singleton to a StaticRefPtr. r=glandium,mixedpuppy - -Differential Revision: https://phabricator.services.mozilla.com/D94692 - -diff -r 5058a78c1008 -r 8de8cd3371e8 toolkit/components/extensions/webrequest/WebRequestService.cpp ---- a/toolkit/components/extensions/webrequest/WebRequestService.cpp Tue Oct 27 15:07:07 2020 +0000 -+++ b/toolkit/components/extensions/webrequest/WebRequestService.cpp Tue Oct 27 15:00:09 2020 +0000 -@@ -13,22 +13,14 @@ - using namespace mozilla::dom; - using namespace mozilla::extensions; - --static WebRequestService* sWeakWebRequestService; -- --WebRequestService::~WebRequestService() { sWeakWebRequestService = nullptr; } -+static StaticRefPtr sWebRequestService; - - /* static */ WebRequestService& WebRequestService::GetSingleton() { -- static RefPtr instance; -- if (!sWeakWebRequestService) { -- instance = new WebRequestService(); -- ClearOnShutdown(&instance); -- -- // A separate weak instance that we keep a reference to as long as the -- // original service is alive, even after our strong reference is cleared to -- // allow the service to be destroyed. -- sWeakWebRequestService = instance; -+ if (!sWebRequestService) { -+ sWebRequestService = new WebRequestService(); -+ ClearOnShutdown(&sWebRequestService); - } -- return *sWeakWebRequestService; -+ return *sWebRequestService; - } - - UniquePtr WebRequestService::RegisterChannel( -@@ -56,7 +48,7 @@ - : mChannelId(aChannel->Id()), mChannel(aChannel) {} - - WebRequestChannelEntry::~WebRequestChannelEntry() { -- if (sWeakWebRequestService) { -- sWeakWebRequestService->mChannelEntries.Remove(mChannelId); -+ if (sWebRequestService) { -+ sWebRequestService->mChannelEntries.Remove(mChannelId); - } - } -diff -r 5058a78c1008 -r 8de8cd3371e8 toolkit/components/extensions/webrequest/WebRequestService.h ---- a/toolkit/components/extensions/webrequest/WebRequestService.h Tue Oct 27 15:07:07 2020 +0000 -+++ b/toolkit/components/extensions/webrequest/WebRequestService.h Tue Oct 27 15:00:09 2020 +0000 -@@ -64,7 +64,7 @@ - dom::ContentParent* aContentParent); - - private: -- ~WebRequestService(); -+ ~WebRequestService() = default; - - friend ChannelEntry; - diff --git a/CVE-2020-26960-1.patch b/CVE-2020-26960-1.patch deleted file mode 100644 index 3e45bf07699b42f8e0dc90d9d396c1a5e52945a6..0000000000000000000000000000000000000000 --- a/CVE-2020-26960-1.patch +++ /dev/null @@ -1,49 +0,0 @@ -# HG changeset patch -# User Jon Coppeard -# Date 1603288236 0 -# Wed Oct 21 13:50:36 2020 +0000 -# Node ID 7e223284a9225c66b590aaad671c7448d1ff0b57 -# Parent dfcb025567da9e33bf724520e0146fef3d776d5f -Bug 1670358 - Don't use realloc for shrinking nsTArrays and similar when RelocationStrategy::allowRealloc is false r=sg - -My original patch handled the grow case but not the shrink case. When the -current and new allocation sizes are in different size classes jemalloc's -realloc will move the allocation when shrinking, not just truncate the existing -one. - -Differential Revision: https://phabricator.services.mozilla.com/D93654 - -diff -r dfcb025567da -r 7e223284a922 xpcom/ds/nsTArray-inl.h ---- a/xpcom/ds/nsTArray-inl.h Thu Oct 22 07:36:15 2020 +0000 -+++ b/xpcom/ds/nsTArray-inl.h Wed Oct 21 13:50:36 2020 +0000 -@@ -259,10 +259,27 @@ - } - - size_type size = sizeof(Header) + length * aElemSize; -- void* ptr = nsTArrayFallibleAllocator::Realloc(mHdr, size); -- if (!ptr) { -- return; -+ void* ptr; -+ -+ if (!RelocationStrategy::allowRealloc) { -+ // Malloc() and copy. -+ ptr = static_cast(nsTArrayFallibleAllocator::Malloc(size)); -+ if (!ptr) { -+ return; -+ } -+ -+ RelocationStrategy::RelocateNonOverlappingRegionWithHeader( -+ ptr, mHdr, Length(), aElemSize); -+ -+ nsTArrayFallibleAllocator::Free(mHdr); -+ } else { -+ // Realloc() existing data. -+ ptr = nsTArrayFallibleAllocator::Realloc(mHdr, size); -+ if (!ptr) { -+ return; -+ } - } -+ - mHdr = static_cast(ptr); - mHdr->mCapacity = length; - } diff --git a/CVE-2020-26960-2.patch b/CVE-2020-26960-2.patch deleted file mode 100644 index 7158a75695f314175a69b7d6e761ef4cda61d6c6..0000000000000000000000000000000000000000 --- a/CVE-2020-26960-2.patch +++ /dev/null @@ -1,136 +0,0 @@ -# HG changeset patch -# User Jon Coppeard -# Date 1603288237 0 -# Wed Oct 21 13:50:37 2020 +0000 -# Node ID 8a8d7fdc7038fb360d7c50f5943ccafd7f0bb829 -# Parent 7e223284a9225c66b590aaad671c7448d1ff0b57 -Bug 1670358 - Add test for shrinking nsTArrays of JS::Heap r=sg - -Depends on D93654 - -Differential Revision: https://phabricator.services.mozilla.com/D94270 - -diff -r 7e223284a922 -r 8a8d7fdc7038 xpcom/tests/gtest/TestGCPostBarriers.cpp ---- a/xpcom/tests/gtest/TestGCPostBarriers.cpp Wed Oct 21 13:50:36 2020 +0000 -+++ b/xpcom/tests/gtest/TestGCPostBarriers.cpp Wed Oct 21 13:50:37 2020 +0000 -@@ -9,6 +9,8 @@ - * implemented for nsTArrays that contain JavaScript Values. - */ - -+#include "mozilla/UniquePtr.h" -+ - #include "jsapi.h" - #include "nsTArray.h" - -@@ -37,11 +39,13 @@ - const size_t InitialElements = ElementCount / 10; - - template --static void RunTest(JSContext* cx, ArrayT* array) { -+static void TestGrow(JSContext* cx) { - JS_GC(cx); - -+ auto array = MakeUnique(); - ASSERT_TRUE(array != nullptr); -- JS_AddExtraGCRootsTracer(cx, TraceArray, array); -+ -+ JS_AddExtraGCRootsTracer(cx, TraceArray, array.get()); - - /* - * Create the array and fill it with new JS objects. With GGC these will be -@@ -66,7 +70,8 @@ - /* - * Sanity check that our array contains what we expect. - */ -- for (size_t i = 0; i < ElementCount; ++i) { -+ ASSERT_EQ(array->Length(), ElementCount); -+ for (size_t i = 0; i < array->Length(); i++) { - RootedObject obj(cx, array->ElementAt(i)); - ASSERT_TRUE(JS::ObjectIsTenured(obj)); - ASSERT_TRUE(JS_GetProperty(cx, obj, property, &value)); -@@ -74,7 +79,54 @@ - ASSERT_EQ(static_cast(i), value.toInt32()); - } - -- JS_RemoveExtraGCRootsTracer(cx, TraceArray, array); -+ JS_RemoveExtraGCRootsTracer(cx, TraceArray, array.get()); -+} -+ -+template -+static void TestShrink(JSContext* cx) { -+ JS_GC(cx); -+ -+ auto array = MakeUnique(); -+ ASSERT_TRUE(array != nullptr); -+ -+ JS_AddExtraGCRootsTracer(cx, TraceArray, array.get()); -+ -+ /* -+ * Create the array and fill it with new JS objects. With GGC these will be -+ * allocated in the nursery. -+ */ -+ RootedValue value(cx); -+ const char* property = "foo"; -+ for (size_t i = 0; i < ElementCount; ++i) { -+ RootedObject obj(cx, JS_NewPlainObject(cx)); -+ ASSERT_FALSE(JS::ObjectIsTenured(obj)); -+ value = Int32Value(i); -+ ASSERT_TRUE(JS_SetProperty(cx, obj, property, value)); -+ ASSERT_TRUE(array->AppendElement(obj, fallible)); -+ } -+ -+ /* Shrink and compact the array */ -+ array->RemoveElementsAt(InitialElements, ElementCount - InitialElements); -+ array->Compact(); -+ -+ JS_GC(cx); -+ -+ ASSERT_EQ(array->Length(), InitialElements); -+ for (size_t i = 0; i < array->Length(); i++) { -+ RootedObject obj(cx, array->ElementAt(i)); -+ ASSERT_TRUE(JS::ObjectIsTenured(obj)); -+ ASSERT_TRUE(JS_GetProperty(cx, obj, property, &value)); -+ ASSERT_TRUE(value.isInt32()); -+ ASSERT_EQ(static_cast(i), value.toInt32()); -+ } -+ -+ JS_RemoveExtraGCRootsTracer(cx, TraceArray, array.get()); -+} -+ -+template -+static void TestArrayType(JSContext* cx) { -+ TestGrow(cx); -+ TestShrink(cx); - } - - static void CreateGlobalAndRunTest(JSContext* cx) { -@@ -89,25 +141,11 @@ - - JS::Realm* oldRealm = JS::EnterRealm(cx, global); - -- typedef Heap ElementT; -- -- { -- nsTArray* array = new nsTArray(InitialElements); -- RunTest(cx, array); -- delete array; -- } -+ using ElementT = Heap; - -- { -- FallibleTArray* array = -- new FallibleTArray(InitialElements); -- RunTest(cx, array); -- delete array; -- } -- -- { -- AutoTArray array; -- RunTest(cx, &array); -- } -+ TestArrayType>(cx); -+ TestArrayType>(cx); -+ TestArrayType>(cx); - - JS::LeaveRealm(cx, oldRealm); - } diff --git a/CVE-2020-26961-1.patch b/CVE-2020-26961-1.patch deleted file mode 100644 index 638b5a355d677c5cb13fa5fa59d73d4156ac7d82..0000000000000000000000000000000000000000 --- a/CVE-2020-26961-1.patch +++ /dev/null @@ -1,58 +0,0 @@ -# HG changeset patch -# User Valentin Gosu -# Date 1604497734 0 -# Wed Nov 04 13:48:54 2020 +0000 -# Node ID 179e399ac08119ef3da61766c73f265679a6cf51 -# Parent 6810172b5a5861dbf847848d0a34f13787c1a6ba -Bug 1672528 - Check IPv4-mapped IPv6 addresses for being local r=dragana,necko-reviewers - -Differential Revision: https://phabricator.services.mozilla.com/D95414 - -diff -r 6810172b5a58 -r 179e399ac081 netwerk/dns/DNS.cpp ---- a/netwerk/dns/DNS.cpp Wed Nov 04 17:16:26 2020 +0000 -+++ b/netwerk/dns/DNS.cpp Wed Nov 04 13:48:54 2020 +0000 -@@ -183,27 +183,37 @@ bool IsIPAddrV4Mapped(const NetAddr* add - return false; - } - -+static bool isLocalIPv4(uint32_t networkEndianIP) { -+ uint32_t addr32 = ntohl(networkEndianIP); -+ if (addr32 >> 24 == 0x0A || // 10/8 prefix (RFC 1918). -+ addr32 >> 20 == 0xAC1 || // 172.16/12 prefix (RFC 1918). -+ addr32 >> 16 == 0xC0A8 || // 192.168/16 prefix (RFC 1918). -+ addr32 >> 16 == 0xA9FE) { // 169.254/16 prefix (Link Local). -+ return true; -+ } -+ return false; -+} -+ - bool IsIPAddrLocal(const NetAddr* addr) { - MOZ_ASSERT(addr); - - // IPv4 RFC1918 and Link Local Addresses. - if (addr->raw.family == AF_INET) { -- uint32_t addr32 = ntohl(addr->inet.ip); -- if (addr32 >> 24 == 0x0A || // 10/8 prefix (RFC 1918). -- addr32 >> 20 == 0xAC1 || // 172.16/12 prefix (RFC 1918). -- addr32 >> 16 == 0xC0A8 || // 192.168/16 prefix (RFC 1918). -- addr32 >> 16 == 0xA9FE) { // 169.254/16 prefix (Link Local). -- return true; -- } -+ return isLocalIPv4(addr->inet.ip); - } - // IPv6 Unique and Link Local Addresses. -+ // or mapped IPv4 address - if (addr->raw.family == AF_INET6) { - uint16_t addr16 = ntohs(addr->inet6.ip.u16[0]); - if (addr16 >> 9 == 0xfc >> 1 || // fc00::/7 Unique Local Address. - addr16 >> 6 == 0xfe80 >> 6) { // fe80::/10 Link Local Address. - return true; - } -+ if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip)) { -+ return isLocalIPv4(IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip)); -+ } - } -+ - // Not an IPv4/6 local address. - return false; - } diff --git a/CVE-2020-26961-2.patch b/CVE-2020-26961-2.patch deleted file mode 100644 index 6844985fd32f35bbf1990fb8062bda54b868a25f..0000000000000000000000000000000000000000 --- a/CVE-2020-26961-2.patch +++ /dev/null @@ -1,47 +0,0 @@ -# HG changeset patch -# User Valentin Gosu -# Date 1604497736 0 -# Wed Nov 04 13:48:56 2020 +0000 -# Node ID b18b9e52050cb671b57c011daa4a173fe46aec5a -# Parent 179e399ac08119ef3da61766c73f265679a6cf51 -Bug 1672528 - Test r=necko-reviewers,dragana - -Depends on D95414 - -Differential Revision: https://phabricator.services.mozilla.com/D95415 - -diff -r 179e399ac081 -r b18b9e52050c netwerk/test/unit/test_trr.js ---- a/netwerk/test/unit/test_trr.js Wed Nov 04 13:48:54 2020 +0000 -+++ b/netwerk/test/unit/test_trr.js Wed Nov 04 13:48:56 2020 +0000 -@@ -556,6 +556,19 @@ - !Components.isSuccessCode(inStatus), - `${inStatus} should be an error code` - ); -+ Services.prefs.setCharPref( -+ "network.trr.uri", -+ `https://foo.example.com:${h2Port}/doh?responseIP=::ffff:192.168.0.1` -+ ); -+ [, , inStatus] = await new DNSListener( -+ "rfc1918-ipv6.example.com", -+ undefined, -+ false -+ ); -+ Assert.ok( -+ !Components.isSuccessCode(inStatus), -+ `${inStatus} should be an error code` -+ ); - }); - - // verify RFC1918 address from the server is fine when told so -@@ -568,6 +581,11 @@ - ); - Services.prefs.setBoolPref("network.trr.allow-rfc1918", true); - await new DNSListener("rfc1918.example.com", "192.168.0.1"); -+ Services.prefs.setCharPref( -+ "network.trr.uri", -+ `https://foo.example.com:${h2Port}/doh?responseIP=::ffff:192.168.0.1` -+ ); -+ await new DNSListener("rfc1918-ipv6.example.com", "::ffff:192.168.0.1"); - }); - - // use GET and disable ECS (makes a larger request) diff --git a/CVE-2020-26963-1.patch b/CVE-2020-26963-1.patch deleted file mode 100644 index cb55845514b17ea5467e7a149cefb34912120691..0000000000000000000000000000000000000000 --- a/CVE-2020-26963-1.patch +++ /dev/null @@ -1,371 +0,0 @@ -# HG changeset patch -# User pbz -# Date 1600689290 0 -# Mon Sep 21 11:54:50 2020 +0000 -# Node ID efcefed227f304781326e7c8a52633559a79b6adlist oniguruma.spec -# Parent 32d03662a363850006f648c22e825b3e886b29bc -Bug 1314912 - Rate limit calls to History and Location interfaces. r=smaug9.0-3 - -This adds a rate limit to methods and setters of the History and Location -for non-system callers. -The rate limit is counted per BrowsingContext and can be controlled by prefs. - -This patch is based on the original rate limit patch by :freesamael. - -Differential Revision: https://phabricator.services.mozilla.com/D90136 - -diff -r 32d03662a363 -r efcefed227f3 docshell/base/BrowsingContext.cpp ---- a/docshell/base/BrowsingContext.cpp 2020-07-21 06:49:37.000000000 +0800 -+++ b/docshell/base/BrowsingContext.cpp 2021-01-06 10:22:57.966851379 +0800 -@@ -2459,6 +2459,56 @@ bool BrowsingContext::CanSet(FieldIndex< - return GetBrowserId() == 0 && IsTop() && Children().IsEmpty(); - } - -+nsresult BrowsingContext::CheckLocationChangeRateLimit(CallerType aCallerType) { -+ // We only rate limit non system callers -+ if (aCallerType == CallerType::System) { -+ return NS_OK; -+ } -+ -+ // Fetch rate limiting preferences -+ uint32_t limitCount = -+ StaticPrefs::dom_navigation_locationChangeRateLimit_count(); -+ uint32_t timeSpanSeconds = -+ StaticPrefs::dom_navigation_locationChangeRateLimit_timespan(); -+ -+ // Disable throttling if either of the preferences is set to 0. -+ if (limitCount == 0 || timeSpanSeconds == 0) { -+ return NS_OK; -+ } -+ -+ TimeDuration throttleSpan = TimeDuration::FromSeconds(timeSpanSeconds); -+ -+ if (mLocationChangeRateLimitSpanStart.IsNull() || -+ ((TimeStamp::Now() - mLocationChangeRateLimitSpanStart) > throttleSpan)) { -+ // Initial call or timespan exceeded, reset counter and timespan. -+ mLocationChangeRateLimitSpanStart = TimeStamp::Now(); -+ mLocationChangeRateLimitCount = 1; -+ return NS_OK; -+ } -+ -+ if (mLocationChangeRateLimitCount >= limitCount) { -+ // Rate limit reached -+ -+ Document* doc = GetDocument(); -+ if (doc) { -+ nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,NS_LITERAL_CSTRING("DOM"), doc, -+ nsContentUtils::eDOM_PROPERTIES, -+ "LocChangeFloodingPrevented"); -+ } -+ -+ return NS_ERROR_DOM_SECURITY_ERR; -+ } -+ -+ mLocationChangeRateLimitCount++; -+ return NS_OK; -+} -+ -+void BrowsingContext::ResetLocationChangeRateLimit() { -+ // Resetting the timestamp object will cause the check function to -+ // init again and reset the rate limit. -+ mLocationChangeRateLimitSpanStart = TimeStamp(); -+} -+ - } // namespace dom - - namespace ipc { -diff -r 32d03662a363 -r efcefed227f3 docshell/base/BrowsingContext.h ---- a/docshell/base/BrowsingContext.h 2020-07-21 06:49:37.000000000 +0800 -+++ b/docshell/base/BrowsingContext.h 2021-01-06 10:22:57.954851198 +0800 -@@ -652,6 +652,16 @@ class BrowsingContext : public nsILoadCo - - bool CrossOriginIsolated(); - -+ // Checks if we reached the rate limit for calls to Location and History API. -+ // The rate limit is controlled by the -+ // "dom.navigation.locationChangeRateLimit" prefs. -+ // Rate limit applies per BrowsingContext. -+ // Returns NS_OK if we are below the rate limit and increments the counter. -+ // Returns NS_ERROR_DOM_SECURITY_ERR if limit is reached. -+ nsresult CheckLocationChangeRateLimit(CallerType aCallerType); -+ -+ void ResetLocationChangeRateLimit(); -+ - protected: - virtual ~BrowsingContext(); - BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup, -@@ -932,6 +942,11 @@ class BrowsingContext : public nsILoadCo - - RefPtr mSessionStorageManager; - RefPtr mChildSessionHistory; -+ -+ // Counter and time span for rate limiting Location and History API calls. -+ // Used by CheckLocationChangeRateLimit. Do not apply cross-process. -+ uint32_t mLocationChangeRateLimitCount; -+ mozilla::TimeStamp mLocationChangeRateLimitSpanStart; - }; - - /** -diff -r 32d03662a363 -r efcefed227f3 docshell/shistory/ChildSHistory.cpp ---- a/docshell/shistory/ChildSHistory.cpp 2020-07-21 06:49:37.000000000 +0800 -+++ b/docshell/shistory/ChildSHistory.cpp 2021-01-06 10:22:58.058852764 +0800 -@@ -105,7 +105,14 @@ void ChildSHistory::Go(int32_t aOffset, - } - } - --void ChildSHistory::AsyncGo(int32_t aOffset, bool aRequireUserInteraction) { -+void ChildSHistory::AsyncGo(int32_t aOffset, bool aRequireUserInteraction, -+ CallerType aCallerType, ErrorResult& aRv) { -+ nsresult rv = mBrowsingContext->CheckLocationChangeRateLimit(aCallerType); -+ if (NS_FAILED(rv)) { -+ aRv.Throw(rv); -+ return; -+ } -+ - if (!CanGo(aOffset)) { - return; - } -diff -r 32d03662a363 -r efcefed227f3 docshell/shistory/ChildSHistory.h ---- a/docshell/shistory/ChildSHistory.h 2020-07-21 06:49:37.000000000 +0800 -+++ b/docshell/shistory/ChildSHistory.h 2021-01-06 10:22:58.058852764 +0800 -@@ -64,8 +64,8 @@ class ChildSHistory : public nsISupports - */ - bool CanGo(int32_t aOffset); - void Go(int32_t aOffset, bool aRequireUserInteraction, ErrorResult& aRv); -- void AsyncGo(int32_t aOffset, bool aRequireUserInteraction); -- -+ void AsyncGo(int32_t aOffset, bool aRequireUserInteraction, -+ CallerType aCallerType, ErrorResult& aRv); - void RemovePendingHistoryNavigations(); - - /** -diff -r 32d03662a363 -r efcefed227f3 dom/base/LocationBase.cpp ---- a/dom/base/LocationBase.cpp 2020-07-21 04:53:13.000000000 +0800 -+++ b/dom/base/LocationBase.cpp 2021-01-06 10:22:46.030671698 +0800 -@@ -116,6 +116,16 @@ void LocationBase::SetURI(nsIURI* aURI, - return; - } - -+ CallerType callerType = aSubjectPrincipal.IsSystemPrincipal() -+ ? CallerType::System -+ : CallerType::NonSystem; -+ -+ nsresult rv = bc->CheckLocationChangeRateLimit(callerType); -+ if (NS_FAILED(rv)) { -+ aRv.Throw(rv); -+ return; -+ } -+ - RefPtr loadState = - CheckURL(aURI, aSubjectPrincipal, aRv); - if (aRv.Failed()) { -@@ -141,7 +151,7 @@ void LocationBase::SetURI(nsIURI* aURI, - loadState->SetLoadFlags(nsIWebNavigation::LOAD_FLAGS_NONE); - loadState->SetFirstParty(true); - -- nsresult rv = bc->LoadURI(loadState); -+ rv = bc->LoadURI(loadState); - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(rv); - } -diff -r 32d03662a363 -r efcefed227f3 dom/base/nsHistory.cpp ---- a/dom/base/nsHistory.cpp 2020-07-21 06:49:37.000000000 +0800 -+++ b/dom/base/nsHistory.cpp 2021-01-06 10:22:46.030671698 +0800 -@@ -135,7 +135,7 @@ void nsHistory::GetState(JSContext* aCx, - aResult.setNull(); - } - --void nsHistory::Go(int32_t aDelta, ErrorResult& aRv) { -+void nsHistory::Go(int32_t aDelta, CallerType aCallerType, ErrorResult& aRv) { - nsCOMPtr win(do_QueryReferent(mInnerWindow)); - if (!win || !win->HasActiveDocument()) { - return aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); -@@ -157,15 +157,17 @@ void nsHistory::Go(int32_t aDelta, Error - - // Ignore the return value from Go(), since returning errors from Go() can - // lead to exceptions and a possible leak of history length -+ // AsyncGo throws if we hit the location change rate limit. - if (StaticPrefs::dom_window_history_async()) { -- session_history->AsyncGo(aDelta, /* aRequireUserInteraction = */ false); -+ session_history->AsyncGo(aDelta, /* aRequireUserInteraction = */ false, -+ aCallerType, aRv); - } else { - session_history->Go(aDelta, /* aRequireUserInteraction = */ false, - IgnoreErrors()); - } - } - --void nsHistory::Back(ErrorResult& aRv) { -+void nsHistory::Back(CallerType aCallerType, ErrorResult& aRv) { - nsCOMPtr win(do_QueryReferent(mInnerWindow)); - if (!win || !win->HasActiveDocument()) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); -@@ -181,13 +183,14 @@ void nsHistory::Back(ErrorResult& aRv) { - } - - if (StaticPrefs::dom_window_history_async()) { -- sHistory->AsyncGo(-1, /* aRequireUserInteraction = */ false); -+ sHistory->AsyncGo(-1, /* aRequireUserInteraction = */ false, aCallerType, -+ aRv); - } else { - sHistory->Go(-1, /* aRequireUserInteraction = */ false, IgnoreErrors()); - } - } - --void nsHistory::Forward(ErrorResult& aRv) { -+void nsHistory::Forward(CallerType aCallerType, ErrorResult& aRv) { - nsCOMPtr win(do_QueryReferent(mInnerWindow)); - if (!win || !win->HasActiveDocument()) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); -@@ -203,7 +206,8 @@ void nsHistory::Forward(ErrorResult& aRv - } - - if (StaticPrefs::dom_window_history_async()) { -- sHistory->AsyncGo(1, /* aRequireUserInteraction = */ false); -+ sHistory->AsyncGo(1, /* aRequireUserInteraction = */ false, aCallerType, -+ aRv); - } else { - sHistory->Go(1, /* aRequireUserInteraction = */ false, IgnoreErrors()); - } -@@ -211,19 +215,20 @@ void nsHistory::Forward(ErrorResult& aRv - - void nsHistory::PushState(JSContext* aCx, JS::Handle aData, - const nsAString& aTitle, const nsAString& aUrl, -- ErrorResult& aRv) { -- PushOrReplaceState(aCx, aData, aTitle, aUrl, aRv, false); -+ CallerType aCallerType, ErrorResult& aRv) { -+ PushOrReplaceState(aCx, aData, aTitle, aUrl, aCallerType, aRv, false); - } - - void nsHistory::ReplaceState(JSContext* aCx, JS::Handle aData, - const nsAString& aTitle, const nsAString& aUrl, -- ErrorResult& aRv) { -- PushOrReplaceState(aCx, aData, aTitle, aUrl, aRv, true); -+ CallerType aCallerType, ErrorResult& aRv) { -+ PushOrReplaceState(aCx, aData, aTitle, aUrl, aCallerType, aRv, true); - } - - void nsHistory::PushOrReplaceState(JSContext* aCx, JS::Handle aData, - const nsAString& aTitle, -- const nsAString& aUrl, ErrorResult& aRv, -+ const nsAString& aUrl, -+ CallerType aCallerType, ErrorResult& aRv, - bool aReplace) { - nsCOMPtr win(do_QueryReferent(mInnerWindow)); - if (!win) { -@@ -238,6 +243,15 @@ void nsHistory::PushOrReplaceState(JSCon - return; - } - -+ BrowsingContext* bc = win->GetBrowsingContext(); -+ if (bc) { -+ nsresult rv = bc->CheckLocationChangeRateLimit(aCallerType); -+ if (NS_FAILED(rv)) { -+ aRv.Throw(rv); -+ return; -+ } -+ } -+ - // AddState might run scripts, so we need to hold a strong reference to the - // docShell here to keep it from going away. - nsCOMPtr docShell = win->GetDocShell(); -diff -r 32d03662a363 -r efcefed227f3 dom/base/nsHistory.h ---- a/dom/base/nsHistory.h 2020-07-21 04:53:13.000000000 +0800 -+++ b/dom/base/nsHistory.h 2021-01-06 10:22:46.030671698 +0800 -@@ -42,14 +42,17 @@ class nsHistory final : public nsISuppor - mozilla::ErrorResult& aRv); - void GetState(JSContext* aCx, JS::MutableHandle aResult, - mozilla::ErrorResult& aRv) const; -- void Go(int32_t aDelta, mozilla::ErrorResult& aRv); -- void Back(mozilla::ErrorResult& aRv); -- void Forward(mozilla::ErrorResult& aRv); -+ void Go(int32_t aDelta, mozilla::dom::CallerType aCallerType, -+ mozilla::ErrorResult& aRv); -+ void Back(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv); -+ void Forward(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv); - void PushState(JSContext* aCx, JS::Handle aData, - const nsAString& aTitle, const nsAString& aUrl, -+ mozilla::dom::CallerType aCallerType, - mozilla::ErrorResult& aRv); - void ReplaceState(JSContext* aCx, JS::Handle aData, - const nsAString& aTitle, const nsAString& aUrl, -+ mozilla::dom::CallerType aCallerType, - mozilla::ErrorResult& aRv); - - protected: -@@ -59,6 +62,7 @@ class nsHistory final : public nsISuppor - - void PushOrReplaceState(JSContext* aCx, JS::Handle aData, - const nsAString& aTitle, const nsAString& aUrl, -+ mozilla::dom::CallerType aCallerType, - mozilla::ErrorResult& aRv, bool aReplace); - - already_AddRefed GetSessionHistory() const; -diff -r 32d03662a363 -r efcefed227f3 dom/chrome-webidl/BrowsingContext.webidl ---- a/dom/chrome-webidl/BrowsingContext.webidl 2020-07-21 06:49:37.000000000 +0800 -+++ b/dom/chrome-webidl/BrowsingContext.webidl 2021-01-06 10:22:42.362616481 +0800 -@@ -120,6 +120,9 @@ interface BrowsingContext { - * under the new browser element. - */ - attribute unsigned long long browserId; -+ -+ // Resets the location change rate limit. Used for testing. -+ void resetLocationChangeRateLimit(); - }; - - BrowsingContext includes LoadContextMixin; -diff -r 32d03662a363 -r efcefed227f3 dom/locales/en-US/chrome/dom/dom.properties ---- a/dom/locales/en-US/chrome/dom/dom.properties 2020-07-21 06:49:37.000000000 +0800 -+++ b/dom/locales/en-US/chrome/dom/dom.properties 2021-01-06 10:22:42.418617324 +0800 -@@ -393,3 +393,5 @@ UnknownProtocolNavigationPrevented=Preve - PostMessageSharedMemoryObjectToCrossOriginWarning=Cannot post message containing a shared memory object to a cross-origin window. - # LOCALIZATION NOTE: %S is the URL of the resource in question - UnusedLinkPreloadPending=The resource at “%S” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly. -+# LOCALIZATION NOTE: Do not translate "Location" and "History". -+LocChangeFloodingPrevented=Too many calls to Location or History APIs within a short timeframe. -diff -r 32d03662a363 -r efcefed227f3 dom/webidl/History.webidl ---- a/dom/webidl/History.webidl 2020-07-21 04:53:19.000000000 +0800 -+++ b/dom/webidl/History.webidl 2021-01-06 10:22:42.298615518 +0800 -@@ -21,14 +21,14 @@ interface History { - attribute ScrollRestoration scrollRestoration; - [Throws] - readonly attribute any state; -- [Throws] -+ [Throws, NeedsCallerType] - void go(optional long delta = 0); -- [Throws] -+ [Throws, NeedsCallerType] - void back(); -- [Throws] -+ [Throws, NeedsCallerType] - void forward(); -- [Throws] -+ [Throws, NeedsCallerType] - void pushState(any data, DOMString title, optional DOMString? url = null); -- [Throws] -+ [Throws, NeedsCallerType] - void replaceState(any data, DOMString title, optional DOMString? url = null); - }; -diff -r 32d03662a363 -r efcefed227f3 modules/libpref/init/StaticPrefList.yaml ---- a/modules/libpref/init/StaticPrefList.yaml 2021-01-06 10:25:09.272827991 +0800 -+++ b/modules/libpref/init/StaticPrefList.yaml 2021-01-06 10:22:36.458527604 +0800 -@@ -2181,6 +2181,19 @@ - value: true - mirror: always - -+# Limit of location change caused by content scripts in a time span per -+# BrowsingContext. This includes calls to History and Location APIs. -+- name: dom.navigation.locationChangeRateLimit.count -+ type: uint32_t -+ value: 200 -+ mirror: always -+ -+# Time span in seconds for location change rate limit. -+- name: dom.navigation.locationChangeRateLimit.timespan -+ type: uint32_t -+ value: 10 -+ mirror: always -+ - # Network Information API - - name: dom.netinfo.enabled - type: RelaxedAtomicBool diff --git a/CVE-2020-26963-2.patch b/CVE-2020-26963-2.patch deleted file mode 100644 index 90a3ba5467949a0723576a9492499aa12dd30e82..0000000000000000000000000000000000000000 --- a/CVE-2020-26963-2.patch +++ /dev/null @@ -1,118 +0,0 @@ -# HG changeset patch -# User pbz -# Date 1600689297 0 -# Mon Sep 21 11:54:57 2020 +0000 -# Node ID ff5164e4aec8cd7a86df0b5f97842fb1f6f765a6 -# Parent efcefed227f304781326e7c8a52633559a79b6ad -Bug 1314912 - Added test for location change rate limit. r=smaug - -Differential Revision: https://phabricator.services.mozilla.com/D90137 - -diff -r efcefed227f3 -r ff5164e4aec8 docshell/test/navigation/mochitest.ini ---- a/docshell/test/navigation/mochitest.ini Mon Sep 21 11:54:50 2020 +0000 -+++ b/docshell/test/navigation/mochitest.ini Mon Sep 21 11:54:57 2020 +0000 -@@ -97,3 +97,4 @@ - [test_triggeringprincipal_parent_iframe_window_open.html] - [test_triggeringprincipal_iframe_iframe_window_open.html] - [test_contentpolicy_block_window.html] -+[test_rate_limit_location_change.html] -diff -r efcefed227f3 -r ff5164e4aec8 docshell/test/navigation/test_rate_limit_location_change.html ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/docshell/test/navigation/test_rate_limit_location_change.html Mon Sep 21 11:54:57 2020 +0000 -@@ -0,0 +1,96 @@ -+ -+ -+ -+ -+ -+ Test for Bug 1314912 -+ -+ -+ -+ -+ -+Mozilla Bug 1314912 -+

-+ -+
-+
-+ -+ diff --git a/CVE-2020-26965.patch b/CVE-2020-26965.patch deleted file mode 100644 index 12f4d5b8745ab4b3835fca074285fb55db822340..0000000000000000000000000000000000000000 --- a/CVE-2020-26965.patch +++ /dev/null @@ -1,28 +0,0 @@ -# HG changeset patch -# User Makoto Kato -# Date 1601537039 0 -# Thu Oct 01 07:23:59 2020 +0000 -# Node ID 3b746525d6472490b44e55e4766078372e0380c3 -# Parent e6b1234900b328782dd4f93b34222bf49b470ac2 -Bug 1661617 - Use password hint for software keyboard. r=masayuki - -Differential Revision: https://phabricator.services.mozilla.com/D91237 - -diff -r e6b1234900b3 -r 3b746525d647 dom/events/IMEStateManager.cpp ---- a/dom/events/IMEStateManager.cpp Thu Oct 08 05:39:33 2020 +0000 -+++ b/dom/events/IMEStateManager.cpp Thu Oct 01 07:23:59 2020 +0000 -@@ -1260,7 +1260,13 @@ - } - - if (aContent->IsHTMLElement(nsGkAtoms::input)) { -- HTMLInputElement::FromNode(aContent)->GetType(context.mHTMLInputType); -+ HTMLInputElement* inputElement = HTMLInputElement::FromNode(aContent); -+ if (inputElement->HasBeenTypePassword() && aState.IsEditable()) { -+ context.mHTMLInputType.AssignLiteral("password"); -+ } else { -+ inputElement->GetType(context.mHTMLInputType); -+ } -+ - GetActionHint(*aContent, context.mActionHint); - } else if (aContent->IsHTMLElement(nsGkAtoms::textarea)) { - context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String()); diff --git a/CVE-2020-26966.patch b/CVE-2020-26966.patch deleted file mode 100644 index 859a814c500f784064c61f6f6dbcf163faa848c9..0000000000000000000000000000000000000000 --- a/CVE-2020-26966.patch +++ /dev/null @@ -1,312 +0,0 @@ -# HG changeset patch -# User Valentin Gosu -# Date 1604045785 0 -# Fri Oct 30 08:16:25 2020 +0000 -# Node ID 0344d5a76b7db85d4f6d5f5f34649b9111eb6094 -# Parent 3e57839bffd2ea7c3b53a9f7ccd75fd308afd801 -Bug 1663571 - Resolve single label DNS queries using DnsQuery_A r=necko-reviewers,dragana - -Differential Revision: https://phabricator.services.mozilla.com/D91117 - -diff -r 3e57839bffd2 -r 0344d5a76b7d modules/libpref/init/StaticPrefList.yaml ---- a/modules/libpref/init/StaticPrefList.yaml Fri Oct 30 10:19:14 2020 +0000 -+++ b/modules/libpref/init/StaticPrefList.yaml Fri Oct 30 08:16:25 2020 +0000 -@@ -7978,6 +7978,14 @@ - value: 2000 - mirror: always - -+# When true on Windows DNS resolutions for single label domains -+# (domains that don't contain a dot) will be resolved using the DnsQuery -+# API instead of PR_GetAddrInfoByName -+- name: network.dns.dns_query_single_label -+ type: RelaxedAtomicBool -+ value: true -+ mirror: always -+ - # Whether the SOCKS proxy should be in charge of DNS resolution. - - name: network.proxy.socks_remote_dns - type: bool -diff -r 3e57839bffd2 -r 0344d5a76b7d netwerk/dns/GetAddrInfo.cpp ---- a/netwerk/dns/GetAddrInfo.cpp Fri Oct 30 10:19:14 2020 +0000 -+++ b/netwerk/dns/GetAddrInfo.cpp Fri Oct 30 08:16:25 2020 +0000 -@@ -5,6 +5,18 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - #include "GetAddrInfo.h" -+ -+#ifdef DNSQUERY_AVAILABLE -+// There is a bug in windns.h where the type of parameter ppQueryResultsSet for -+// DnsQuery_A is dependent on UNICODE being set. It should *always* be -+// PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this -+// we make sure that UNICODE is unset. -+# undef UNICODE -+# include -+# undef GetAddrInfo -+# include -+#endif // DNSQUERY_AVAILABLE -+ - #include "mozilla/ClearOnShutdown.h" - #include "mozilla/net/DNS.h" - #include "NativeDNSResolverOverrideParent.h" -@@ -19,17 +31,6 @@ - #include "mozilla/Logging.h" - #include "mozilla/StaticPrefs_network.h" - --#ifdef DNSQUERY_AVAILABLE --// There is a bug in windns.h where the type of parameter ppQueryResultsSet for --// DnsQuery_A is dependent on UNICODE being set. It should *always* be --// PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this --// we make sure that UNICODE is unset. --# undef UNICODE --# include --# undef GetAddrInfo --# include --#endif -- - namespace mozilla { - namespace net { - -@@ -42,6 +43,11 @@ - MOZ_LOG(gGetAddrInfoLog, LogLevel::Warning, ("[DNS]: " msg, ##__VA_ARGS__)) - - #ifdef DNSQUERY_AVAILABLE -+ -+# define COMPUTER_NAME_BUFFER_SIZE 100 -+static char sDNSComputerName[COMPUTER_NAME_BUFFER_SIZE]; -+static char sNETBIOSComputerName[MAX_COMPUTERNAME_LENGTH + 1]; -+ - //////////////////////////// - // WINDOWS IMPLEMENTATION // - //////////////////////////// -@@ -56,45 +62,63 @@ - // equal with the one already there. Gets the TTL value by calling - // to DnsQuery_A and iterating through the returned - // records to find the one with the smallest TTL value. --static MOZ_ALWAYS_INLINE nsresult _GetMinTTLForRequestType_Windows( -- const char* aHost, uint16_t aRequestType, unsigned int* aResult) { -- MOZ_ASSERT(aHost); -- MOZ_ASSERT(aResult); -+static MOZ_ALWAYS_INLINE nsresult _CallDnsQuery_A_Windows( -+ const nsACString& aHost, uint16_t aAddressFamily, DWORD aFlags, -+ std::function aCallback) { -+ NS_ConvertASCIItoUTF16 name(aHost); -+ -+ auto callDnsQuery_A = [&](uint16_t reqFamily) { -+ PDNS_RECORDA dnsData = nullptr; -+ DNS_STATUS status = DnsQuery_A(aHost.BeginReading(), reqFamily, aFlags, -+ nullptr, &dnsData, nullptr); -+ if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR || -+ !dnsData) { -+ LOG("No DNS records found for %s. status=%X. reqFamily = %X\n", -+ aHost.BeginReading(), status, reqFamily); -+ return NS_ERROR_FAILURE; -+ } else if (status != NOERROR) { -+ LOG_WARNING("DnsQuery_A failed with status %X.\n", status); -+ return NS_ERROR_UNEXPECTED; -+ } - -- PDNS_RECORDA dnsData = nullptr; -- DNS_STATUS status = DnsQuery_A( -- aHost, aRequestType, -- (DNS_QUERY_STANDARD | DNS_QUERY_NO_NETBT | DNS_QUERY_NO_HOSTS_FILE | -- DNS_QUERY_NO_MULTICAST | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE | -- DNS_QUERY_DONT_RESET_TTL_VALUES), -- nullptr, &dnsData, nullptr); -- if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR || -- !dnsData) { -- LOG("No DNS records found for %s. status=%X. aRequestType = %X\n", aHost, -- status, aRequestType); -- return NS_ERROR_FAILURE; -- } else if (status != NOERROR) { -- LOG_WARNING("DnsQuery_A failed with status %X.\n", status); -- return NS_ERROR_UNEXPECTED; -+ for (PDNS_RECORDA curRecord = dnsData; curRecord; -+ curRecord = curRecord->pNext) { -+ // Only records in the answer section are important -+ if (curRecord->Flags.S.Section != DnsSectionAnswer) { -+ continue; -+ } -+ if (curRecord->wType != reqFamily) { -+ continue; -+ } -+ -+ aCallback(curRecord); -+ } -+ -+ DnsFree(dnsData, DNS_FREE_TYPE::DnsFreeRecordList); -+ return NS_OK; -+ }; -+ -+ if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET) { -+ callDnsQuery_A(DNS_TYPE_A); - } - -- for (PDNS_RECORDA curRecord = dnsData; curRecord; -- curRecord = curRecord->pNext) { -- // Only records in the answer section are important -- if (curRecord->Flags.S.Section != DnsSectionAnswer) { -- continue; -- } -+ if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET6) { -+ callDnsQuery_A(DNS_TYPE_AAAA); -+ } -+ return NS_OK; -+} - -- if (curRecord->wType == aRequestType) { -- *aResult = std::min(*aResult, curRecord->dwTtl); -- } else { -- LOG("Received unexpected record type %u in response for %s.\n", -- curRecord->wType, aHost); -- } -+bool recordTypeMatchesRequest(uint16_t wType, uint16_t aAddressFamily) { -+ if (aAddressFamily == PR_AF_UNSPEC) { -+ return wType == DNS_TYPE_A || wType == DNS_TYPE_AAAA; - } -- -- DnsFree(dnsData, DNS_FREE_TYPE::DnsFreeRecordList); -- return NS_OK; -+ if (aAddressFamily == PR_AF_INET) { -+ return wType == DNS_TYPE_A; -+ } -+ if (aAddressFamily == PR_AF_INET6) { -+ return wType == DNS_TYPE_AAAA; -+ } -+ return false; - } - - static MOZ_ALWAYS_INLINE nsresult _GetTTLData_Windows(const nsACString& aHost, -@@ -110,13 +134,21 @@ - // In order to avoid using ANY records which are not always implemented as a - // "Gimme what you have" request in hostname resolvers, we should send A - // and/or AAAA requests, based on the address family requested. -+ const DWORD ttlFlags = -+ (DNS_QUERY_STANDARD | DNS_QUERY_NO_NETBT | DNS_QUERY_NO_HOSTS_FILE | -+ DNS_QUERY_NO_MULTICAST | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE | -+ DNS_QUERY_DONT_RESET_TTL_VALUES); - unsigned int ttl = (unsigned int)-1; -- if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET) { -- _GetMinTTLForRequestType_Windows(aHost.BeginReading(), DNS_TYPE_A, &ttl); -- } -- if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET6) { -- _GetMinTTLForRequestType_Windows(aHost.BeginReading(), DNS_TYPE_AAAA, &ttl); -- } -+ _CallDnsQuery_A_Windows( -+ aHost, aAddressFamily, ttlFlags, -+ [&ttl, &aHost, aAddressFamily](PDNS_RECORDA curRecord) { -+ if (recordTypeMatchesRequest(curRecord->wType, aAddressFamily)) { -+ ttl = std::min(ttl, curRecord->dwTtl); -+ } else { -+ LOG("Received unexpected record type %u in response for %s.\n", -+ curRecord->wType, aHost.BeginReading()); -+ } -+ }); - - if (ttl == (unsigned int)-1) { - LOG("No useable TTL found."); -@@ -126,6 +158,41 @@ - *aResult = ttl; - return NS_OK; - } -+ -+static MOZ_ALWAYS_INLINE nsresult -+_DNSQuery_A_SingleLabel(const nsACString& aCanonHost, uint16_t aAddressFamily, -+ uint16_t aFlags, AddrInfo** aAddrInfo) { -+ bool setCanonName = aFlags & nsHostResolver::RES_CANON_NAME; -+ nsAutoCString canonName; -+ const DWORD flags = (DNS_QUERY_STANDARD | DNS_QUERY_NO_MULTICAST | -+ DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE); -+ nsTArray addresses; -+ -+ _CallDnsQuery_A_Windows( -+ aCanonHost, aAddressFamily, flags, [&](PDNS_RECORDA curRecord) { -+ MOZ_DIAGNOSTIC_ASSERT(curRecord->wType == DNS_TYPE_A || -+ curRecord->wType == DNS_TYPE_AAAA); -+ if (setCanonName) { -+ canonName.Assign(curRecord->pName); -+ } -+ NetAddr addr{}; -+ addr.inet.family = AF_INET; -+ addr.inet.ip = curRecord->Data.A.IpAddress; -+ addresses.AppendElement(addr); -+ }); -+ -+ LOG("Query for: %s has %u results", aCanonHost.BeginReading(), -+ addresses.Length()); -+ if (addresses.IsEmpty()) { -+ return NS_ERROR_UNKNOWN_HOST; -+ } -+ RefPtr ai( -+ new AddrInfo(aCanonHost, canonName, 0, std::move(addresses))); -+ ai.forget(aAddrInfo); -+ -+ return NS_OK; -+} -+ - #endif - - //////////////////////////////////// -@@ -153,6 +220,24 @@ - aAddressFamily = PR_AF_UNSPEC; - } - -+#if defined(DNSQUERY_AVAILABLE) -+ if (StaticPrefs::network_dns_dns_query_single_label() && -+ !aCanonHost.Contains('.') && aCanonHost != NS_LITERAL_CSTRING("localhost")) { -+ // For some reason we can't use DnsQuery_A to get the computer's IP. -+ if (!aCanonHost.Equals(nsDependentCString(sDNSComputerName), -+ nsCaseInsensitiveCStringComparator) && -+ !aCanonHost.Equals(nsDependentCString(sNETBIOSComputerName), -+ nsCaseInsensitiveCStringComparator)) { -+ // This is a single label name resolve without a dot. -+ // We use DNSQuery_A for these. -+ LOG("Resolving %s using DnsQuery_A (computername: %s)\n", -+ aCanonHost.BeginReading(), sDNSComputerName); -+ return _DNSQuery_A_SingleLabel(aCanonHost, aAddressFamily, aFlags, -+ aAddrInfo); -+ } -+ } -+#endif -+ - PRAddrInfo* prai = - PR_GetAddrInfoByName(aCanonHost.BeginReading(), aAddressFamily, prFlags); - -@@ -184,6 +269,19 @@ - ////////////////////////////////////// - nsresult GetAddrInfoInit() { - LOG("Initializing GetAddrInfo.\n"); -+ -+#ifdef DNSQUERY_AVAILABLE -+ DWORD namesize = COMPUTER_NAME_BUFFER_SIZE; -+ if (!GetComputerNameEx(ComputerNameDnsHostname, sDNSComputerName, -+ &namesize)) { -+ sDNSComputerName[0] = 0; -+ } -+ namesize = MAX_COMPUTERNAME_LENGTH + 1; -+ if (!GetComputerNameEx(ComputerNameNetBIOS, sNETBIOSComputerName, -+ &namesize)) { -+ sNETBIOSComputerName[0] = 0; -+ } -+#endif - return NS_OK; - } - -diff -r 3e57839bffd2 -r 0344d5a76b7d netwerk/dns/moz.build ---- a/netwerk/dns/moz.build Fri Oct 30 10:19:14 2020 +0000 -+++ b/netwerk/dns/moz.build Fri Oct 30 08:16:25 2020 +0000 -@@ -54,6 +54,7 @@ - ] - - SOURCES += [ -+ 'GetAddrInfo.cpp', # Undefines UNICODE - 'nsEffectiveTLDService.cpp', # Excluded from UNIFIED_SOURCES due to special build flags. - 'nsHostResolver.cpp', # Redefines LOG - ] -@@ -65,7 +66,6 @@ - 'DNSRequestChild.cpp', - 'DNSRequestParent.cpp', -- 'GetAddrInfo.cpp', - 'HTTPSSVC.cpp', - 'IDNBlocklistUtils.cpp', - 'NativeDNSResolverOverrideChild.cpp', - 'NativeDNSResolverOverrideParent.cpp', diff --git a/CVE-2020-26967.patch b/CVE-2020-26967.patch deleted file mode 100644 index 90f1db15faed42bcc7bb9eaf4aa1e214c5be3f2e..0000000000000000000000000000000000000000 --- a/CVE-2020-26967.patch +++ /dev/null @@ -1,21 +0,0 @@ -# HG changeset patch -# User Kaizer Soze -# Date 1602665311 0 -# Wed Oct 14 08:48:31 2020 +0000 -# Node ID 5a4b06d86f52685f2a4b51538f9ac3a7d9be265b -# Parent 1547b1a7189503e22eaa2180fa9597a044b91ff8 -Bug 1665820, r=emalysz - -Differential Revision: https://phabricator.services.mozilla.com/D92589 - -diff -r 1547b1a71895 -r 5a4b06d86f52 browser/extensions/screenshots/selector/ui.js ---- a/browser/extensions/screenshots/selector/ui.js Wed Oct 14 09:17:27 2020 +0000 -+++ b/browser/extensions/screenshots/selector/ui.js Wed Oct 14 08:48:31 2020 +0000 -@@ -361,6 +361,7 @@ - this.element.setAttribute("role", "dialog"); - this.element.onload = watchFunction(() => { - msgsPromise.then(([cancelTitle, copyTitle, downloadTitle]) => { -+ assertIsBlankDocument(this.element.contentDocument); - this.document = this.element.contentDocument; - // eslint-disable-next-line no-unsanitized/property - this.document.documentElement.innerHTML = ` diff --git a/D110204-fscreen.patch b/D110204-fscreen.patch new file mode 100644 index 0000000000000000000000000000000000000000..c25f992fd9663055d571017ba82a7e8323c4be71 --- /dev/null +++ b/D110204-fscreen.patch @@ -0,0 +1,82 @@ +diff -up firefox-102.2.0/widget/gtk/nsWindow.cpp.D110204-fscreen.diff firefox-102.2.0/widget/gtk/nsWindow.cpp +--- firefox-102.2.0/widget/gtk/nsWindow.cpp.D110204-fscreen.diff 2022-08-18 21:54:09.000000000 +0200 ++++ firefox-102.2.0/widget/gtk/nsWindow.cpp 2022-09-02 15:55:18.023843940 +0200 +@@ -96,6 +96,7 @@ + #include "ScreenHelperGTK.h" + #include "SystemTimeConverter.h" + #include "WidgetUtilsGtk.h" ++#include "nsIBrowserHandler.h" + + #ifdef ACCESSIBILITY + # include "mozilla/a11y/LocalAccessible.h" +@@ -169,7 +170,8 @@ const gint kEvents = GDK_TOUCHPAD_GESTUR + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_SMOOTH_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SCROLL_MASK | +- GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK; ++ GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK | ++ GDK_FOCUS_CHANGE_MASK; + + /* utility functions */ + static bool is_mouse_in_window(GdkWindow* aWindow, gdouble aMouseX, +@@ -408,7 +410,8 @@ nsWindow::nsWindow() + mMovedAfterMoveToRect(false), + mResizedAfterMoveToRect(false), + mConfiguredClearColor(false), +- mGotNonBlankPaint(false) { ++ mGotNonBlankPaint(false), ++ mPendingFullscreen(false) { + mWindowType = eWindowType_child; + mSizeConstraints.mMaxSize = GetSafeWindowSize(mSizeConstraints.mMaxSize); + +@@ -4814,6 +4817,19 @@ void nsWindow::OnWindowStateEvent(GtkWid + ClearTransparencyBitmap(); + } + } ++ ++ // Hack to ensure window switched to fullscreen - avoid to fail when starting ++ // in kiosk mode ++ if (mPendingFullscreen && ++ !(aEvent->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { ++ LOG( ++ " Window should be fullscreen, but it's not, retrying set to " ++ "fullscreen.\n"); ++ MakeFullScreen(true); ++ } else { ++ LOG(" Window successfully switched to fullscreen, happy now\n"); ++ mPendingFullscreen = false; ++ } + } + + void nsWindow::OnDPIChanged() { +@@ -7042,6 +7058,19 @@ nsresult nsWindow::MakeFullScreen(bool a + } + } + ++ // if in kiosk, ensure the fullscreen is called ++ nsCOMPtr browserHandler = ++ do_GetService("@mozilla.org/browser/clh;1"); ++ if (browserHandler) { ++ bool isKiosk; ++ browserHandler->GetKiosk(&isKiosk); ++ if (isKiosk) { ++ LOG(" is kiosk, ensure the window switch to fullscreen\n"); ++ mPendingFullscreen = true; ++ } ++ } else { ++ LOG(" Cannot find the browserHandler service.\n"); ++ } + gtk_window_fullscreen(GTK_WINDOW(mShell)); + } else { + mSizeMode = mLastSizeMode; +diff -up firefox-102.2.0/widget/gtk/nsWindow.h.D110204-fscreen.diff firefox-102.2.0/widget/gtk/nsWindow.h +--- firefox-102.2.0/widget/gtk/nsWindow.h.D110204-fscreen.diff 2022-08-18 21:53:52.000000000 +0200 ++++ firefox-102.2.0/widget/gtk/nsWindow.h 2022-09-02 08:17:07.606010905 +0200 +@@ -712,6 +712,7 @@ class nsWindow final : public nsBaseWidg + * move-to-rect callback we set mMovedAfterMoveToRect/mResizedAfterMoveToRect. + */ + bool mWaitingForMoveToRectCallback : 1; ++ bool mPendingFullscreen : 1; + bool mMovedAfterMoveToRect : 1; + bool mResizedAfterMoveToRect : 1; + diff --git a/expat-CVE-2022-40674.patch b/D158770.patch similarity index 100% rename from expat-CVE-2022-40674.patch rename to D158770.patch diff --git a/Deny-clone3-to-force-glibc-fallback.patch b/Deny-clone3-to-force-glibc-fallback.patch deleted file mode 100644 index 1626b1075b8a69f7ff15f25a2e01bbf4abc39a88..0000000000000000000000000000000000000000 --- a/Deny-clone3-to-force-glibc-fallback.patch +++ /dev/null @@ -1,54 +0,0 @@ - -# HG changeset patch -# User Alexandre Lissy -# Date 1623246328 0 -# Node ID ecb4011a0c76a1c7040054a44712e277f3dc24a1 -# Parent 9ec189804055442e5cc98d69dd01b71e90ed0cb5 -Bug 1715254 - Deny clone3 to force glibc fallback r=gcp - -Differential Revision: https://phabricator.services.mozilla.com/D117297 - -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -853,16 +853,19 @@ class SandboxPolicyCommon : public Sandb - // Yield - case __NR_sched_yield: - return Allow(); - - // Thread creation. - case __NR_clone: - return ClonePolicy(InvalidSyscall()); - -+ case __NR_clone3: -+ return Error(ENOSYS); -+ - // More thread creation. - #ifdef __NR_set_robust_list - case __NR_set_robust_list: - return Allow(); - #endif - #ifdef ANDROID - case __NR_set_tid_address: - return Allow(); -@@ -1499,16 +1502,19 @@ class ContentSandboxPolicy : public Sand - // the child would inherit the seccomp-bpf policy and almost - // certainly die from an unexpected SIGSYS. We also can't have - // fork() crash, currently, because there are too many system - // libraries/plugins that try to run commands. But they can - // usually do something reasonable on error. - case __NR_clone: - return ClonePolicy(Error(EPERM)); - -+ case __NR_clone3: -+ return Error(ENOSYS); -+ - # ifdef __NR_fadvise64 - case __NR_fadvise64: - return Allow(); - # endif - - # ifdef __NR_fadvise64_64 - case __NR_fadvise64_64: - return Allow(); - diff --git a/Fix-build-with-rust-nightly.patch b/Fix-build-with-rust-nightly.patch deleted file mode 100644 index c74eeb223c37ec39dcba58086c58b4fd2d974b1d..0000000000000000000000000000000000000000 --- a/Fix-build-with-rust-nightly.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 99c71d0db95b3626552a1375d5dfba22dc82ebfd Mon Sep 17 00:00:00 2001 -From: lingsheng -Date: Fri, 30 Apr 2021 17:11:51 +0800 -Subject: [PATCH] Fix build with rust nightly - ---- - .cargo/config.in | 2 +- - Cargo.lock | 2 +- - Cargo.toml | 4 ++-- - 3 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/.cargo/config.in b/.cargo/config.in -index a40e667b5a..c95e6e016b 100644 ---- a/.cargo/config.in -+++ b/.cargo/config.in -@@ -3,9 +3,9 @@ - # Please do not edit. - - [source."https://github.com/shravanrn/nix/"] --branch = "r0.13.1" - git = "https://github.com/shravanrn/nix/" - replace-with = "vendored-sources" -+rev = "4af6c367603869a30fddb5ffb0aba2b9477ba92e" - - [source."https://github.com/mozilla/rkv"] - git = "https://github.com/mozilla/rkv" -diff --git a/Cargo.lock b/Cargo.lock -index 0b61796d7d..e97e8d080b 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -3196,7 +3196,7 @@ dependencies = [ - [[package]] - name = "nix" - version = "0.13.1" --source = "git+https://github.com/shravanrn/nix/?branch=r0.13.1#4af6c367603869a30fddb5ffb0aba2b9477ba92e" -+source = "git+https://github.com/shravanrn/nix/?rev=4af6c367603869a30fddb5ffb0aba2b9477ba92e#4af6c367603869a30fddb5ffb0aba2b9477ba92e" - dependencies = [ - "bitflags", - "cc", -diff --git a/Cargo.toml b/Cargo.toml -index 0b7ec008b8..910a62ee57 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -67,8 +67,8 @@ panic = "abort" - libudev-sys = { path = "dom/webauthn/libudev-sys" } - packed_simd = { git = "https://github.com/hsivonen/packed_simd", rev="3541e3818fdc7c2a24f87e3459151a4ce955a67a" } - rlbox_lucet_sandbox = { git = "https://github.com/PLSysSec/rlbox_lucet_sandbox/", rev="d510da5999a744c563b0acd18056069d1698273f" } --nix = { git = "https://github.com/shravanrn/nix/", branch = "r0.13.1", rev="4af6c367603869a30fddb5ffb0aba2b9477ba92e" } --spirv_cross = { git = "https://github.com/kvark/spirv_cross", branch = "wgpu3", rev = "20191ad2f370afd6d247edcb9ff9da32d3bedb9c" } -+nix = { git = "https://github.com/shravanrn/nix/", rev="4af6c367603869a30fddb5ffb0aba2b9477ba92e" } -+spirv_cross = { git = "https://github.com/kvark/spirv_cross", branch = "wgpu3" } - # failure's backtrace feature might break our builds, see bug 1608157. - failure = { git = "https://github.com/badboy/failure", rev = "64af847bc5fdcb6d2438bec8a6030812a80519a5" } - failure_derive = { git = "https://github.com/badboy/failure", rev = "64af847bc5fdcb6d2438bec8a6030812a80519a5" } --- -2.23.0 - diff --git a/Teach-style_derives-map_type_params-about-mapping-self-correctly.patch b/Teach-style_derives-map_type_params-about-mapping-self-correctly.patch deleted file mode 100644 index b54e8135a4a825be36b892f828e8ca2c6a6c802b..0000000000000000000000000000000000000000 --- a/Teach-style_derives-map_type_params-about-mapping-self-correctly.patch +++ /dev/null @@ -1,211 +0,0 @@ - -# HG changeset patch -# User Emilio Cobos Álvarez -# Date 1594925481 0 -# Node ID da77d5528a0819c4e61a92f642542b55da81183e -# Parent 5e9a7815de712ddc8ab5bb784b644a03e5f2e6b4 -Bug 1653339 - Teach style_derive's map_type_params about mapping self correctly. r=boris - -Consider the following: - -struct Complex { - something: T, - #[compute(field_bound)] - something_else: Generic, -} - -That will generate: - -impl ToComputedValue for Complex -where - T: ToComputedValue, - Generic: ToComputedValue::ComputedValue>>, -{ - // ... -} - -That last clause is obviously incorrect. map_type_params correctly maps -the T, but it should know also about Self. - -Ideally we could just do the same as for T and do: - - ::ComputedValue - -But that doesn't quite work, because we are in that implementation of -the trait, and the compiler rightfully complains about we don't yet -knowing the computed type. So we need to pass it explicitly, which is -simple enough, if a bit annoying. - -Differential Revision: https://phabricator.services.mozilla.com/D83816 - -diff --git a/servo/components/derive_common/cg.rs b/servo/components/derive_common/cg.rs ---- a/servo/components/derive_common/cg.rs -+++ b/servo/components/derive_common/cg.rs -@@ -149,79 +149,85 @@ pub fn fmap_trait_output(input: &DeriveI - colon2_token: Default::default(), - gt_token: Default::default(), - lt_token: Default::default(), - }), - }; - segment.into() - } - --pub fn map_type_params(ty: &Type, params: &[&TypeParam], f: &mut F) -> Type -+pub fn map_type_params(ty: &Type, params: &[&TypeParam], self_type: &Path, f: &mut F) -> Type - where - F: FnMut(&Ident) -> Type, - { - match *ty { - Type::Slice(ref inner) => Type::from(TypeSlice { -- elem: Box::new(map_type_params(&inner.elem, params, f)), -+ elem: Box::new(map_type_params(&inner.elem, params, self_type, f)), - ..inner.clone() - }), - Type::Array(ref inner) => { - //ref ty, ref expr) => { - Type::from(TypeArray { -- elem: Box::new(map_type_params(&inner.elem, params, f)), -+ elem: Box::new(map_type_params(&inner.elem, params, self_type, f)), - ..inner.clone() - }) - }, - ref ty @ Type::Never(_) => ty.clone(), - Type::Tuple(ref inner) => Type::from(TypeTuple { - elems: inner - .elems - .iter() -- .map(|ty| map_type_params(&ty, params, f)) -+ .map(|ty| map_type_params(&ty, params, self_type, f)) - .collect(), - ..inner.clone() - }), - Type::Path(TypePath { - qself: None, - ref path, - }) => { - if let Some(ident) = path_to_ident(path) { - if params.iter().any(|ref param| ¶m.ident == ident) { - return f(ident); - } -+ if ident == "Self" { -+ return Type::from(TypePath { -+ qself: None, -+ path: self_type.clone(), -+ }); -+ } - } - Type::from(TypePath { - qself: None, -- path: map_type_params_in_path(path, params, f), -+ path: map_type_params_in_path(path, params, self_type, f), - }) - }, - Type::Path(TypePath { - ref qself, - ref path, - }) => Type::from(TypePath { - qself: qself.as_ref().map(|qself| QSelf { -- ty: Box::new(map_type_params(&qself.ty, params, f)), -+ ty: Box::new(map_type_params(&qself.ty, params, self_type, f)), - position: qself.position, - ..qself.clone() - }), -- path: map_type_params_in_path(path, params, f), -+ path: map_type_params_in_path(path, params, self_type, f), - }), - Type::Paren(ref inner) => Type::from(TypeParen { -- elem: Box::new(map_type_params(&inner.elem, params, f)), -+ elem: Box::new(map_type_params(&inner.elem, params, self_type, f)), - ..inner.clone() - }), - Type::Group(ref inner) => Type::from(TypeGroup { -- elem: Box::new(map_type_params(&inner.elem, params, f)), -+ elem: Box::new(map_type_params(&inner.elem, params, self_type, f)), - ..inner.clone() - }), - ref ty => panic!("type {:?} cannot be mapped yet", ty), - } - } - --fn map_type_params_in_path(path: &Path, params: &[&TypeParam], f: &mut F) -> Path -+fn map_type_params_in_path(path: &Path, params: &[&TypeParam], self_type: &Path, f: &mut F) -> Path - where - F: FnMut(&Ident) -> Type, - { - Path { - leading_colon: path.leading_colon, - segments: path - .segments - .iter() -@@ -231,21 +237,21 @@ where - PathArguments::AngleBracketed(ref data) => { - PathArguments::AngleBracketed(AngleBracketedGenericArguments { - args: data - .args - .iter() - .map(|arg| match arg { - ty @ &GenericArgument::Lifetime(_) => ty.clone(), - &GenericArgument::Type(ref data) => { -- GenericArgument::Type(map_type_params(data, params, f)) -+ GenericArgument::Type(map_type_params(data, params, self_type, f)) - }, - &GenericArgument::Binding(ref data) => { - GenericArgument::Binding(Binding { -- ty: map_type_params(&data.ty, params, f), -+ ty: map_type_params(&data.ty, params, self_type, f), - ..data.clone() - }) - }, - ref arg => panic!("arguments {:?} cannot be mapped yet", arg), - }) - .collect(), - ..data.clone() - }) -diff --git a/servo/components/style_derive/to_computed_value.rs b/servo/components/style_derive/to_computed_value.rs ---- a/servo/components/style_derive/to_computed_value.rs -+++ b/servo/components/style_derive/to_computed_value.rs -@@ -42,22 +42,25 @@ pub fn derive_to_value( - BindStyle::Ref | BindStyle::RefMut => false, - }; - - let params = input.generics.type_params().collect::>(); - for param in ¶ms { - cg::add_predicate(&mut where_clause, parse_quote!(#param: #trait_path)); - } - -+ let computed_value_type = cg::fmap_trait_output(&input, &trait_path, &output_type_name); -+ - let mut add_field_bound = |binding: &BindingInfo| { - let ty = &binding.ast().ty; - - let output_type = cg::map_type_params( - ty, - ¶ms, -+ &computed_value_type, - &mut |ident| parse_quote!(<#ident as #trait_path>::#output_type_name), - ); - - cg::add_predicate( - &mut where_clause, - parse_quote!( - #ty: #trait_path<#output_type_name = #output_type> - ), -@@ -137,17 +140,16 @@ pub fn derive_to_value( - } - }; - - (to_body, from_body) - }; - - input.generics.where_clause = where_clause; - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); -- let computed_value_type = cg::fmap_trait_output(&input, &trait_path, &output_type_name); - - let impl_ = trait_impl(from_body, to_body); - - quote! { - impl #impl_generics #trait_path for #name #ty_generics #where_clause { - type #output_type_name = #computed_value_type; - - #impl_ - diff --git a/Update-syn-and-proc-macro2-so-that-Firefox-can-build-on-Rust-nightly-again.patch b/Update-syn-and-proc-macro2-so-that-Firefox-can-build-on-Rust-nightly-again.patch deleted file mode 100644 index 332fd811cc5b024bda4cedd6b356a3f990054a8d..0000000000000000000000000000000000000000 --- a/Update-syn-and-proc-macro2-so-that-Firefox-can-build-on-Rust-nightly-again.patch +++ /dev/null @@ -1,35278 +0,0 @@ - -# HG changeset patch -# User Emilio Cobos Álvarez -# Date 1599584448 0 -# Node ID 85c38ea4d34969797eb5d24265cd90cc6841e6ae -# Parent 5aa243a2fe9d77578dd95ce3ab3a2aa6c1e92604 -Bug 1663715 - Update syn and proc-macro2 so that Firefox can build on Rust nightly again. r=froydnj, a=RyanVM - -Generated with: - - cargo update -p syn --precise 1.0.40 - ./mach vendor rust - -Rust issue: https://github.com/rust-lang/rust/issues/76482 - -Differential Revision: https://phabricator.services.mozilla.com/D89473 - -diff --git a/Cargo.lock b/Cargo.lock ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -3712,19 +3712,19 @@ checksum = "ecd45702f76d6d3c75a80564378a - dependencies = [ - "proc-macro2", - "quote", - "syn", - ] - - [[package]] - name = "proc-macro2" --version = "1.0.5" --source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" -+version = "1.0.20" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29" - dependencies = [ - "unicode-xid", - ] - - [[package]] - name = "procedural-masquerade" - version = "0.1.1" - source = "registry+https://github.com/rust-lang/crates.io-index" -@@ -4642,19 +4642,19 @@ dependencies = [ - "cc", - "gleam", - "glsl-to-cxx", - "webrender_build", - ] - - [[package]] - name = "syn" --version = "1.0.5" --source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -+version = "1.0.40" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350" - dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", - ] - - [[package]] - name = "sync-guid" -diff --git a/third_party/rust/proc-macro2/.cargo-checksum.json b/third_party/rust/proc-macro2/.cargo-checksum.json ---- a/third_party/rust/proc-macro2/.cargo-checksum.json -+++ b/third_party/rust/proc-macro2/.cargo-checksum.json -@@ -1,1 +1,1 @@ --{"files":{"Cargo.toml":"e2c1fc6ed317eeef8462fcd192f6b6389e1d84f0d7afeac78f12c23903deddf8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"362a2156f7645528061b6e8487a2eb0f32f1693012ed82ee57afa05c039bba0d","build.rs":"0cc6e2cb919ddbff59cf1d810283939f97a59f0037540c0f2ee3453237635ff8","src/fallback.rs":"5c6379a90735e27abcc40253b223158c6b1e5784f3850bc423335363e87ef038","src/lib.rs":"ae5251296ad3fcd8b600919a993fec0afd8b56da3e11fef6bc7265b273129936","src/strnom.rs":"37f7791f73f123817ad5403af1d4e2a0714be27401729a2d451bc80b1f26bac9","src/wrapper.rs":"81372e910604217a625aa71c47d43e65f4e008456eae93ac39325c9abf10701a","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"c2652e3ae1dfcb94d2e6313b29712c5dcbd0fe62026913e67bb7cebd7560aade","tests/test.rs":"8c427be9cba1fa8d4a16647e53e3545e5863e29e2c0b311c93c9dd1399abf6a1"},"package":"90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0"} -\ No newline at end of file -+{"files":{"Cargo.toml":"c20c4c52342e65ea11ad8382edc636e628e8f8c5ab7cffddc32426b2fe8fe4cd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e1f9d4fc22cff2c049f166a403b41458632a94357890d31cf0e3ad83807fb430","build.rs":"332185d7ad4c859210f5edd7a76bc95146c8277726a2f81417f34927c4424d68","src/detection.rs":"9d25d896889e65330858f2d6f6223c1b98cd1dad189813ad4161ff189fbda2b8","src/fallback.rs":"239f9a25c0f2ab57592288d944c7f1a0f887536b6d4dc2428a17640af8d10a41","src/lib.rs":"2b1d98424c9b23b547dabf85554120e5e65472026a0f3f711b3a097bca7c32fe","src/parse.rs":"500edee9773132e27e44d0fdaa042b1cb9451e29e65124493986f51710c0664c","src/wrapper.rs":"d36c0dced7ec0e7585c1f935cda836080bcae6de1de3d7851d962e9e11a3ac48","tests/comments.rs":"ea6cbe6f4c8852e6a0612893c7d4f2c144a2e6a134a6c3db641a320cbfc3c800","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"c2652e3ae1dfcb94d2e6313b29712c5dcbd0fe62026913e67bb7cebd7560aade","tests/test.rs":"310c856e27ff61c9ec7f0a5cd96031aac02971557b1621f5e17b089d58e79bcd","tests/test_fmt.rs":"745dfdc41d09c5308c221395eb43f2041f0a1413d2927a813bc2ad4554438fe2"},"package":"175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29"} -\ No newline at end of file -diff --git a/third_party/rust/proc-macro2/Cargo.toml b/third_party/rust/proc-macro2/Cargo.toml ---- a/third_party/rust/proc-macro2/Cargo.toml -+++ b/third_party/rust/proc-macro2/Cargo.toml -@@ -8,36 +8,35 @@ - # If you believe there's an error in this file please file an - # issue against the rust-lang/cargo repository. If you're - # editing this file be aware that the upstream Cargo.toml - # will likely look very different (and much more reasonable) - - [package] - edition = "2018" - name = "proc-macro2" --version = "1.0.5" --authors = ["Alex Crichton "] --description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n" --homepage = "https://github.com/alexcrichton/proc-macro2" -+version = "1.0.20" -+authors = ["Alex Crichton ", "David Tolnay "] -+description = "A substitute implementation of the compiler's `proc_macro` API to decouple\ntoken-based libraries from the procedural macro use case.\n" - documentation = "https://docs.rs/proc-macro2" - readme = "README.md" - keywords = ["macros"] -+categories = ["development-tools::procedural-macro-helpers"] - license = "MIT OR Apache-2.0" - repository = "https://github.com/alexcrichton/proc-macro2" - [package.metadata.docs.rs] - rustc-args = ["--cfg", "procmacro2_semver_exempt"] - rustdoc-args = ["--cfg", "procmacro2_semver_exempt"] -+targets = ["x86_64-unknown-linux-gnu"] - --[lib] --name = "proc_macro2" -+[package.metadata.playground] -+features = ["span-locations"] - [dependencies.unicode-xid] - version = "0.2" - [dev-dependencies.quote] - version = "1.0" - default_features = false - - [features] - default = ["proc-macro"] - nightly = [] - proc-macro = [] - span-locations = [] --[badges.travis-ci] --repository = "alexcrichton/proc-macro2" -diff --git a/third_party/rust/proc-macro2/README.md b/third_party/rust/proc-macro2/README.md ---- a/third_party/rust/proc-macro2/README.md -+++ b/third_party/rust/proc-macro2/README.md -@@ -1,11 +1,11 @@ - # proc-macro2 - --[![Build Status](https://api.travis-ci.com/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.com/alexcrichton/proc-macro2) -+[![Build Status](https://img.shields.io/github/workflow/status/alexcrichton/proc-macro2/build%20and%20test)](https://github.com/alexcrichton/proc-macro2/actions) - [![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2) - [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2) - - A wrapper around the procedural macro API of the compiler's `proc_macro` crate. - This library serves two purposes: - - - **Bring proc-macro-like functionality to other contexts like build.rs and - main.rs.** Types from `proc_macro` are entirely specific to procedural macros -diff --git a/third_party/rust/proc-macro2/build.rs b/third_party/rust/proc-macro2/build.rs ---- a/third_party/rust/proc-macro2/build.rs -+++ b/third_party/rust/proc-macro2/build.rs -@@ -9,16 +9,20 @@ - // "wrap_proc_macro" - // Wrap types from libproc_macro rather than polyfilling the whole API. - // Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set, - // because we can't emulate the unstable API without emulating everything - // else. Also enabled unconditionally on nightly, in which case the - // procmacro2_semver_exempt surface area is implemented by using the - // nightly-only proc_macro API. - // -+// "hygiene" -+// Enable Span::mixed_site() and non-dummy behavior of Span::resolved_at -+// and Span::located_at. Enabled on Rust 1.45+. -+// - // "proc_macro_span" - // Enable non-dummy behavior of Span::start and Span::end methods which - // requires an unstable compiler feature. Enabled when building with - // nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable - // features. - // - // "super_unstable" - // Implement the semver exempt API in terms of the nightly-only proc_macro -@@ -52,16 +56,24 @@ fn main() { - // https://github.com/alexcrichton/proc-macro2/issues/147 - println!("cargo:rustc-cfg=procmacro2_semver_exempt"); - } - - if semver_exempt || cfg!(feature = "span-locations") { - println!("cargo:rustc-cfg=span_locations"); - } - -+ if version.minor < 39 { -+ println!("cargo:rustc-cfg=no_bind_by_move_pattern_guard"); -+ } -+ -+ if version.minor >= 45 { -+ println!("cargo:rustc-cfg=hygiene"); -+ } -+ - let target = env::var("TARGET").unwrap(); - if !enable_use_proc_macro(&target) { - return; - } - - println!("cargo:rustc-cfg=use_proc_macro"); - - if version.nightly || !semver_exempt { -diff --git a/third_party/rust/proc-macro2/src/detection.rs b/third_party/rust/proc-macro2/src/detection.rs -new file mode 100644 ---- /dev/null -+++ b/third_party/rust/proc-macro2/src/detection.rs -@@ -0,0 +1,67 @@ -+use std::panic::{self, PanicInfo}; -+use std::sync::atomic::*; -+use std::sync::Once; -+ -+static WORKS: AtomicUsize = AtomicUsize::new(0); -+static INIT: Once = Once::new(); -+ -+pub(crate) fn inside_proc_macro() -> bool { -+ match WORKS.load(Ordering::SeqCst) { -+ 1 => return false, -+ 2 => return true, -+ _ => {} -+ } -+ -+ INIT.call_once(initialize); -+ inside_proc_macro() -+} -+ -+pub(crate) fn force_fallback() { -+ WORKS.store(1, Ordering::SeqCst); -+} -+ -+pub(crate) fn unforce_fallback() { -+ initialize(); -+} -+ -+// Swap in a null panic hook to avoid printing "thread panicked" to stderr, -+// then use catch_unwind to determine whether the compiler's proc_macro is -+// working. When proc-macro2 is used from outside of a procedural macro all -+// of the proc_macro crate's APIs currently panic. -+// -+// The Once is to prevent the possibility of this ordering: -+// -+// thread 1 calls take_hook, gets the user's original hook -+// thread 1 calls set_hook with the null hook -+// thread 2 calls take_hook, thinks null hook is the original hook -+// thread 2 calls set_hook with the null hook -+// thread 1 calls set_hook with the actual original hook -+// thread 2 calls set_hook with what it thinks is the original hook -+// -+// in which the user's hook has been lost. -+// -+// There is still a race condition where a panic in a different thread can -+// happen during the interval that the user's original panic hook is -+// unregistered such that their hook is incorrectly not called. This is -+// sufficiently unlikely and less bad than printing panic messages to stderr -+// on correct use of this crate. Maybe there is a libstd feature request -+// here. For now, if a user needs to guarantee that this failure mode does -+// not occur, they need to call e.g. `proc_macro2::Span::call_site()` from -+// the main thread before launching any other threads. -+fn initialize() { -+ type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; -+ -+ let null_hook: Box = Box::new(|_panic_info| { /* ignore */ }); -+ let sanity_check = &*null_hook as *const PanicHook; -+ let original_hook = panic::take_hook(); -+ panic::set_hook(null_hook); -+ -+ let works = panic::catch_unwind(proc_macro::Span::call_site).is_ok(); -+ WORKS.store(works as usize + 1, Ordering::SeqCst); -+ -+ let hopefully_null_hook = panic::take_hook(); -+ panic::set_hook(original_hook); -+ if sanity_check != &*hopefully_null_hook { -+ panic!("observed race condition in proc_macro2::inside_proc_macro"); -+ } -+} -diff --git a/third_party/rust/proc-macro2/src/fallback.rs b/third_party/rust/proc-macro2/src/fallback.rs ---- a/third_party/rust/proc-macro2/src/fallback.rs -+++ b/third_party/rust/proc-macro2/src/fallback.rs -@@ -1,41 +1,121 @@ -+use crate::parse::{token_stream, Cursor}; -+use crate::{Delimiter, Spacing, TokenTree}; - #[cfg(span_locations)] - use std::cell::RefCell; - #[cfg(span_locations)] - use std::cmp; --use std::fmt; --use std::iter; -+use std::fmt::{self, Debug, Display}; -+use std::iter::FromIterator; -+use std::mem; - use std::ops::RangeBounds; - #[cfg(procmacro2_semver_exempt)] - use std::path::Path; - use std::path::PathBuf; - use std::str::FromStr; - use std::vec; -- --use crate::strnom::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult}; --use crate::{Delimiter, Punct, Spacing, TokenTree}; - use unicode_xid::UnicodeXID; - -+/// Force use of proc-macro2's fallback implementation of the API for now, even -+/// if the compiler's implementation is available. -+pub fn force() { -+ #[cfg(wrap_proc_macro)] -+ crate::detection::force_fallback(); -+} -+ -+/// Resume using the compiler's implementation of the proc macro API if it is -+/// available. -+pub fn unforce() { -+ #[cfg(wrap_proc_macro)] -+ crate::detection::unforce_fallback(); -+} -+ - #[derive(Clone)] --pub struct TokenStream { -- inner: Vec, -+pub(crate) struct TokenStream { -+ pub(crate) inner: Vec, - } - - #[derive(Debug)] --pub struct LexError; -+pub(crate) struct LexError; - - impl TokenStream { - pub fn new() -> TokenStream { - TokenStream { inner: Vec::new() } - } - - pub fn is_empty(&self) -> bool { - self.inner.len() == 0 - } -+ -+ fn take_inner(&mut self) -> Vec { -+ mem::replace(&mut self.inner, Vec::new()) -+ } -+ -+ fn push_token(&mut self, token: TokenTree) { -+ // https://github.com/alexcrichton/proc-macro2/issues/235 -+ match token { -+ #[cfg(not(no_bind_by_move_pattern_guard))] -+ TokenTree::Literal(crate::Literal { -+ #[cfg(wrap_proc_macro)] -+ inner: crate::imp::Literal::Fallback(literal), -+ #[cfg(not(wrap_proc_macro))] -+ inner: literal, -+ .. -+ }) if literal.text.starts_with('-') => { -+ push_negative_literal(self, literal); -+ } -+ #[cfg(no_bind_by_move_pattern_guard)] -+ TokenTree::Literal(crate::Literal { -+ #[cfg(wrap_proc_macro)] -+ inner: crate::imp::Literal::Fallback(literal), -+ #[cfg(not(wrap_proc_macro))] -+ inner: literal, -+ .. -+ }) => { -+ if literal.text.starts_with('-') { -+ push_negative_literal(self, literal); -+ } else { -+ self.inner -+ .push(TokenTree::Literal(crate::Literal::_new_stable(literal))); -+ } -+ } -+ _ => self.inner.push(token), -+ } -+ -+ #[cold] -+ fn push_negative_literal(stream: &mut TokenStream, mut literal: Literal) { -+ literal.text.remove(0); -+ let mut punct = crate::Punct::new('-', Spacing::Alone); -+ punct.set_span(crate::Span::_new_stable(literal.span)); -+ stream.inner.push(TokenTree::Punct(punct)); -+ stream -+ .inner -+ .push(TokenTree::Literal(crate::Literal::_new_stable(literal))); -+ } -+ } -+} -+ -+// Nonrecursive to prevent stack overflow. -+impl Drop for TokenStream { -+ fn drop(&mut self) { -+ while let Some(token) = self.inner.pop() { -+ let group = match token { -+ TokenTree::Group(group) => group.inner, -+ _ => continue, -+ }; -+ #[cfg(wrap_proc_macro)] -+ let group = match group { -+ crate::imp::Group::Fallback(group) => group, -+ _ => continue, -+ }; -+ let mut group = group; -+ self.inner.extend(group.stream.take_inner()); -+ } -+ } - } - - #[cfg(span_locations)] - fn get_cursor(src: &str) -> Cursor { - // Create a dummy file & add it to the source map - SOURCE_MAP.with(|cm| { - let mut cm = cm.borrow_mut(); - let name = format!("", cm.files.len()); -@@ -54,68 +134,49 @@ fn get_cursor(src: &str) -> Cursor { - - impl FromStr for TokenStream { - type Err = LexError; - - fn from_str(src: &str) -> Result { - // Create a dummy file & add it to the source map - let cursor = get_cursor(src); - -- match token_stream(cursor) { -- Ok((input, output)) => { -- if skip_whitespace(input).len() != 0 { -- Err(LexError) -- } else { -- Ok(output) -- } -- } -- Err(LexError) => Err(LexError), -+ let (rest, tokens) = token_stream(cursor)?; -+ if rest.is_empty() { -+ Ok(tokens) -+ } else { -+ Err(LexError) - } - } - } - --impl fmt::Display for TokenStream { -+impl Display for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut joint = false; - for (i, tt) in self.inner.iter().enumerate() { - if i != 0 && !joint { - write!(f, " ")?; - } - joint = false; -- match *tt { -- TokenTree::Group(ref tt) => { -- let (start, end) = match tt.delimiter() { -- Delimiter::Parenthesis => ("(", ")"), -- Delimiter::Brace => ("{", "}"), -- Delimiter::Bracket => ("[", "]"), -- Delimiter::None => ("", ""), -- }; -- if tt.stream().into_iter().next().is_none() { -- write!(f, "{} {}", start, end)? -- } else { -- write!(f, "{} {} {}", start, tt.stream(), end)? -- } -+ match tt { -+ TokenTree::Group(tt) => Display::fmt(tt, f), -+ TokenTree::Ident(tt) => Display::fmt(tt, f), -+ TokenTree::Punct(tt) => { -+ joint = tt.spacing() == Spacing::Joint; -+ Display::fmt(tt, f) - } -- TokenTree::Ident(ref tt) => write!(f, "{}", tt)?, -- TokenTree::Punct(ref tt) => { -- write!(f, "{}", tt.as_char())?; -- match tt.spacing() { -- Spacing::Alone => {} -- Spacing::Joint => joint = true, -- } -- } -- TokenTree::Literal(ref tt) => write!(f, "{}", tt)?, -- } -+ TokenTree::Literal(tt) => Display::fmt(tt, f), -+ }? - } - - Ok(()) - } - } - --impl fmt::Debug for TokenStream { -+impl Debug for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("TokenStream ")?; - f.debug_list().entries(self.clone()).finish() - } - } - - #[cfg(use_proc_macro)] - impl From for TokenStream { -@@ -134,122 +195,107 @@ impl From for proc_macro::T - .to_string() - .parse() - .expect("failed to parse to compiler tokens") - } - } - - impl From for TokenStream { - fn from(tree: TokenTree) -> TokenStream { -- TokenStream { inner: vec![tree] } -+ let mut stream = TokenStream::new(); -+ stream.push_token(tree); -+ stream - } - } - --impl iter::FromIterator for TokenStream { -- fn from_iter>(streams: I) -> Self { -- let mut v = Vec::new(); -- -- for token in streams.into_iter() { -- v.push(token); -- } -- -- TokenStream { inner: v } -+impl FromIterator for TokenStream { -+ fn from_iter>(tokens: I) -> Self { -+ let mut stream = TokenStream::new(); -+ stream.extend(tokens); -+ stream - } - } - --impl iter::FromIterator for TokenStream { -+impl FromIterator for TokenStream { - fn from_iter>(streams: I) -> Self { - let mut v = Vec::new(); - -- for stream in streams.into_iter() { -- v.extend(stream.inner); -+ for mut stream in streams { -+ v.extend(stream.take_inner()); - } - - TokenStream { inner: v } - } - } - - impl Extend for TokenStream { -- fn extend>(&mut self, streams: I) { -- self.inner.extend(streams); -+ fn extend>(&mut self, tokens: I) { -+ tokens.into_iter().for_each(|token| self.push_token(token)); - } - } - - impl Extend for TokenStream { - fn extend>(&mut self, streams: I) { -- self.inner -- .extend(streams.into_iter().flat_map(|stream| stream)); -+ self.inner.extend(streams.into_iter().flatten()); - } - } - --pub type TokenTreeIter = vec::IntoIter; -+pub(crate) type TokenTreeIter = vec::IntoIter; - - impl IntoIterator for TokenStream { - type Item = TokenTree; - type IntoIter = TokenTreeIter; - -- fn into_iter(self) -> TokenTreeIter { -- self.inner.into_iter() -+ fn into_iter(mut self) -> TokenTreeIter { -+ self.take_inner().into_iter() - } - } - - #[derive(Clone, PartialEq, Eq)] --pub struct SourceFile { -+pub(crate) struct SourceFile { - path: PathBuf, - } - - impl SourceFile { - /// Get the path to this source file as a string. - pub fn path(&self) -> PathBuf { - self.path.clone() - } - - pub fn is_real(&self) -> bool { - // XXX(nika): Support real files in the future? - false - } - } - --impl fmt::Debug for SourceFile { -+impl Debug for SourceFile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("SourceFile") - .field("path", &self.path()) - .field("is_real", &self.is_real()) - .finish() - } - } - - #[derive(Clone, Copy, Debug, PartialEq, Eq)] --pub struct LineColumn { -+pub(crate) struct LineColumn { - pub line: usize, - pub column: usize, - } - - #[cfg(span_locations)] - thread_local! { - static SOURCE_MAP: RefCell = RefCell::new(SourceMap { - // NOTE: We start with a single dummy file which all call_site() and - // def_site() spans reference. -- files: vec![{ -+ files: vec![FileInfo { - #[cfg(procmacro2_semver_exempt)] -- { -- FileInfo { -- name: "".to_owned(), -- span: Span { lo: 0, hi: 0 }, -- lines: vec![0], -- } -- } -- -- #[cfg(not(procmacro2_semver_exempt))] -- { -- FileInfo { -- span: Span { lo: 0, hi: 0 }, -- lines: vec![0], -- } -- } -+ name: "".to_owned(), -+ span: Span { lo: 0, hi: 0 }, -+ lines: vec![0], - }], - }); - } - - #[cfg(span_locations)] - struct FileInfo { - #[cfg(procmacro2_semver_exempt)] - name: String, -@@ -277,26 +323,31 @@ impl FileInfo { - } - } - - fn span_within(&self, span: Span) -> bool { - span.lo >= self.span.lo && span.hi <= self.span.hi - } - } - --/// Computesthe offsets of each line in the given source string. -+/// Computes the offsets of each line in the given source string -+/// and the total number of characters - #[cfg(span_locations)] --fn lines_offsets(s: &str) -> Vec { -+fn lines_offsets(s: &str) -> (usize, Vec) { - let mut lines = vec![0]; -- let mut prev = 0; -- while let Some(len) = s[prev..].find('\n') { -- prev += len + 1; -- lines.push(prev); -+ let mut total = 0; -+ -+ for ch in s.chars() { -+ total += 1; -+ if ch == '\n' { -+ lines.push(total); -+ } - } -- lines -+ -+ (total, lines) - } - - #[cfg(span_locations)] - struct SourceMap { - files: Vec, - } - - #[cfg(span_locations)] -@@ -305,81 +356,83 @@ impl SourceMap { - // Add 1 so there's always space between files. - // - // We'll always have at least 1 file, as we initialize our files list - // with a dummy file. - self.files.last().unwrap().span.hi + 1 - } - - fn add_file(&mut self, name: &str, src: &str) -> Span { -- let lines = lines_offsets(src); -+ let (len, lines) = lines_offsets(src); - let lo = self.next_start_pos(); - // XXX(nika): Shouild we bother doing a checked cast or checked add here? - let span = Span { - lo, -- hi: lo + (src.len() as u32), -+ hi: lo + (len as u32), - }; - -- #[cfg(procmacro2_semver_exempt)] - self.files.push(FileInfo { -+ #[cfg(procmacro2_semver_exempt)] - name: name.to_owned(), - span, - lines, - }); - - #[cfg(not(procmacro2_semver_exempt))] -- self.files.push(FileInfo { span, lines }); - let _ = name; - - span - } - - fn fileinfo(&self, span: Span) -> &FileInfo { - for file in &self.files { - if file.span_within(span) { - return file; - } - } - panic!("Invalid span with no related FileInfo!"); - } - } - - #[derive(Clone, Copy, PartialEq, Eq)] --pub struct Span { -+pub(crate) struct Span { - #[cfg(span_locations)] -- lo: u32, -+ pub(crate) lo: u32, - #[cfg(span_locations)] -- hi: u32, -+ pub(crate) hi: u32, - } - - impl Span { - #[cfg(not(span_locations))] - pub fn call_site() -> Span { - Span {} - } - - #[cfg(span_locations)] - pub fn call_site() -> Span { - Span { lo: 0, hi: 0 } - } - -+ #[cfg(hygiene)] -+ pub fn mixed_site() -> Span { -+ Span::call_site() -+ } -+ - #[cfg(procmacro2_semver_exempt)] - pub fn def_site() -> Span { - Span::call_site() - } - -- #[cfg(procmacro2_semver_exempt)] - pub fn resolved_at(&self, _other: Span) -> Span { - // Stable spans consist only of line/column information, so - // `resolved_at` and `located_at` only select which span the - // caller wants line/column information from. - *self - } - -- #[cfg(procmacro2_semver_exempt)] - pub fn located_at(&self, other: Span) -> Span { - other - } - - #[cfg(procmacro2_semver_exempt)] - pub fn source_file(&self) -> SourceFile { - SOURCE_MAP.with(|cm| { - let cm = cm.borrow(); -@@ -422,36 +475,69 @@ impl Span { - return None; - } - Some(Span { - lo: cmp::min(self.lo, other.lo), - hi: cmp::max(self.hi, other.hi), - }) - }) - } -+ -+ #[cfg(not(span_locations))] -+ fn first_byte(self) -> Self { -+ self -+ } -+ -+ #[cfg(span_locations)] -+ fn first_byte(self) -> Self { -+ Span { -+ lo: self.lo, -+ hi: cmp::min(self.lo.saturating_add(1), self.hi), -+ } -+ } -+ -+ #[cfg(not(span_locations))] -+ fn last_byte(self) -> Self { -+ self -+ } -+ -+ #[cfg(span_locations)] -+ fn last_byte(self) -> Self { -+ Span { -+ lo: cmp::max(self.hi.saturating_sub(1), self.lo), -+ hi: self.hi, -+ } -+ } - } - --impl fmt::Debug for Span { -+impl Debug for Span { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- #[cfg(procmacro2_semver_exempt)] -+ #[cfg(span_locations)] - return write!(f, "bytes({}..{})", self.lo, self.hi); - -- #[cfg(not(procmacro2_semver_exempt))] -+ #[cfg(not(span_locations))] - write!(f, "Span") - } - } - --pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { -- if cfg!(procmacro2_semver_exempt) { -+pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { -+ #[cfg(span_locations)] -+ { -+ if span.lo == 0 && span.hi == 0 { -+ return; -+ } -+ } -+ -+ if cfg!(span_locations) { - debug.field("span", &span); - } - } - - #[derive(Clone)] --pub struct Group { -+pub(crate) struct Group { - delimiter: Delimiter, - stream: TokenStream, - span: Span, - } - - impl Group { - pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { - Group { -@@ -469,58 +555,67 @@ impl Group { - self.stream.clone() - } - - pub fn span(&self) -> Span { - self.span - } - - pub fn span_open(&self) -> Span { -- self.span -+ self.span.first_byte() - } - - pub fn span_close(&self) -> Span { -- self.span -+ self.span.last_byte() - } - - pub fn set_span(&mut self, span: Span) { - self.span = span; - } - } - --impl fmt::Display for Group { -+impl Display for Group { -+ // We attempt to match libproc_macro's formatting. -+ // Empty parens: () -+ // Nonempty parens: (...) -+ // Empty brackets: [] -+ // Nonempty brackets: [...] -+ // Empty braces: { } -+ // Nonempty braces: { ... } - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- let (left, right) = match self.delimiter { -+ let (open, close) = match self.delimiter { - Delimiter::Parenthesis => ("(", ")"), -- Delimiter::Brace => ("{", "}"), -+ Delimiter::Brace => ("{ ", "}"), - Delimiter::Bracket => ("[", "]"), - Delimiter::None => ("", ""), - }; - -- f.write_str(left)?; -- self.stream.fmt(f)?; -- f.write_str(right)?; -+ f.write_str(open)?; -+ Display::fmt(&self.stream, f)?; -+ if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() { -+ f.write_str(" ")?; -+ } -+ f.write_str(close)?; - - Ok(()) - } - } - --impl fmt::Debug for Group { -+impl Debug for Group { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut debug = fmt.debug_struct("Group"); - debug.field("delimiter", &self.delimiter); - debug.field("stream", &self.stream); -- #[cfg(procmacro2_semver_exempt)] -- debug.field("span", &self.span); -+ debug_span_field_if_nontrivial(&mut debug, self.span); - debug.finish() - } - } - - #[derive(Clone)] --pub struct Ident { -+pub(crate) struct Ident { - sym: String, - span: Span, - raw: bool, - } - - impl Ident { - fn _new(string: &str, raw: bool, span: Span) -> Ident { - validate_ident(string); -@@ -544,26 +639,24 @@ impl Ident { - self.span - } - - pub fn set_span(&mut self, span: Span) { - self.span = span; - } - } - --#[inline] --fn is_ident_start(c: char) -> bool { -+pub(crate) fn is_ident_start(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || c == '_' - || (c > '\x7f' && UnicodeXID::is_xid_start(c)) - } - --#[inline] --fn is_ident_continue(c: char) -> bool { -+pub(crate) fn is_ident_continue(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || c == '_' - || ('0' <= c && c <= '9') - || (c > '\x7f' && UnicodeXID::is_xid_continue(c)) - } - - fn validate_ident(string: &str) { -@@ -610,49 +703,49 @@ where - if self.raw { - other.starts_with("r#") && self.sym == other[2..] - } else { - self.sym == other - } - } - } - --impl fmt::Display for Ident { -+impl Display for Ident { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.raw { -- "r#".fmt(f)?; -+ f.write_str("r#")?; - } -- self.sym.fmt(f) -+ Display::fmt(&self.sym, f) - } - } - --impl fmt::Debug for Ident { -+impl Debug for Ident { - // Ident(proc_macro), Ident(r#union) -- #[cfg(not(procmacro2_semver_exempt))] -+ #[cfg(not(span_locations))] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut debug = f.debug_tuple("Ident"); - debug.field(&format_args!("{}", self)); - debug.finish() - } - - // Ident { - // sym: proc_macro, - // span: bytes(128..138) - // } -- #[cfg(procmacro2_semver_exempt)] -+ #[cfg(span_locations)] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut debug = f.debug_struct("Ident"); - debug.field("sym", &format_args!("{}", self)); -- debug.field("span", &self.span); -+ debug_span_field_if_nontrivial(&mut debug, self.span); - debug.finish() - } - } - - #[derive(Clone)] --pub struct Literal { -+pub(crate) struct Literal { - text: String, - span: Span, - } - - macro_rules! suffixed_numbers { - ($($name:ident => $kind:ident,)*) => ($( - pub fn $name(n: $kind) -> Literal { - Literal::_new(format!(concat!("{}", stringify!($kind)), n)) -@@ -664,17 +757,17 @@ macro_rules! unsuffixed_numbers { - ($($name:ident => $kind:ident,)*) => ($( - pub fn $name(n: $kind) -> Literal { - Literal::_new(n.to_string()) - } - )*) - } - - impl Literal { -- fn _new(text: String) -> Literal { -+ pub(crate) fn _new(text: String) -> Literal { - Literal { - text, - span: Span::call_site(), - } - } - - suffixed_numbers! { - u8_suffixed => u8, -@@ -706,61 +799,62 @@ impl Literal { - i32_unsuffixed => i32, - i64_unsuffixed => i64, - i128_unsuffixed => i128, - isize_unsuffixed => isize, - } - - pub fn f32_unsuffixed(f: f32) -> Literal { - let mut s = f.to_string(); -- if !s.contains(".") { -+ if !s.contains('.') { - s.push_str(".0"); - } - Literal::_new(s) - } - - pub fn f64_unsuffixed(f: f64) -> Literal { - let mut s = f.to_string(); -- if !s.contains(".") { -+ if !s.contains('.') { - s.push_str(".0"); - } - Literal::_new(s) - } - - pub fn string(t: &str) -> Literal { - let mut text = String::with_capacity(t.len() + 2); - text.push('"'); - for c in t.chars() { - if c == '\'' { -- // escape_default turns this into "\'" which is unnecessary. -+ // escape_debug turns this into "\'" which is unnecessary. - text.push(c); - } else { -- text.extend(c.escape_default()); -+ text.extend(c.escape_debug()); - } - } - text.push('"'); - Literal::_new(text) - } - - pub fn character(t: char) -> Literal { - let mut text = String::new(); - text.push('\''); - if t == '"' { -- // escape_default turns this into '\"' which is unnecessary. -+ // escape_debug turns this into '\"' which is unnecessary. - text.push(t); - } else { -- text.extend(t.escape_default()); -+ text.extend(t.escape_debug()); - } - text.push('\''); - Literal::_new(text) - } - - pub fn byte_string(bytes: &[u8]) -> Literal { - let mut escaped = "b\"".to_string(); - for b in bytes { -+ #[allow(clippy::match_overlapping_arm)] - match *b { - b'\0' => escaped.push_str(r"\0"), - b'\t' => escaped.push_str(r"\t"), - b'\n' => escaped.push_str(r"\n"), - b'\r' => escaped.push_str(r"\r"), - b'"' => escaped.push_str("\\\""), - b'\\' => escaped.push_str("\\\\"), - b'\x20'..=b'\x7E' => escaped.push(*b as char), -@@ -779,656 +873,22 @@ impl Literal { - self.span = span; - } - - pub fn subspan>(&self, _range: R) -> Option { - None - } - } - --impl fmt::Display for Literal { -+impl Display for Literal { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.text.fmt(f) -- } --} -- --impl fmt::Debug for Literal { -- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { -- let mut debug = fmt.debug_struct("Literal"); -- debug.field("lit", &format_args!("{}", self.text)); -- #[cfg(procmacro2_semver_exempt)] -- debug.field("span", &self.span); -- debug.finish() -- } --} -- --fn token_stream(mut input: Cursor) -> PResult { -- let mut trees = Vec::new(); -- loop { -- let input_no_ws = skip_whitespace(input); -- if input_no_ws.rest.len() == 0 { -- break; -- } -- if let Ok((a, tokens)) = doc_comment(input_no_ws) { -- input = a; -- trees.extend(tokens); -- continue; -- } -- -- let (a, tt) = match token_tree(input_no_ws) { -- Ok(p) => p, -- Err(_) => break, -- }; -- trees.push(tt); -- input = a; -- } -- Ok((input, TokenStream { inner: trees })) --} -- --#[cfg(not(span_locations))] --fn spanned<'a, T>( -- input: Cursor<'a>, -- f: fn(Cursor<'a>) -> PResult<'a, T>, --) -> PResult<'a, (T, crate::Span)> { -- let (a, b) = f(skip_whitespace(input))?; -- Ok((a, ((b, crate::Span::_new_stable(Span::call_site()))))) --} -- --#[cfg(span_locations)] --fn spanned<'a, T>( -- input: Cursor<'a>, -- f: fn(Cursor<'a>) -> PResult<'a, T>, --) -> PResult<'a, (T, crate::Span)> { -- let input = skip_whitespace(input); -- let lo = input.off; -- let (a, b) = f(input)?; -- let hi = a.off; -- let span = crate::Span::_new_stable(Span { lo, hi }); -- Ok((a, (b, span))) --} -- --fn token_tree(input: Cursor) -> PResult { -- let (rest, (mut tt, span)) = spanned(input, token_kind)?; -- tt.set_span(span); -- Ok((rest, tt)) --} -- --named!(token_kind -> TokenTree, alt!( -- map!(group, |g| TokenTree::Group(crate::Group::_new_stable(g))) -- | -- map!(literal, |l| TokenTree::Literal(crate::Literal::_new_stable(l))) // must be before symbol -- | -- map!(op, TokenTree::Punct) -- | -- symbol_leading_ws --)); -- --named!(group -> Group, alt!( -- delimited!( -- punct!("("), -- token_stream, -- punct!(")") -- ) => { |ts| Group::new(Delimiter::Parenthesis, ts) } -- | -- delimited!( -- punct!("["), -- token_stream, -- punct!("]") -- ) => { |ts| Group::new(Delimiter::Bracket, ts) } -- | -- delimited!( -- punct!("{"), -- token_stream, -- punct!("}") -- ) => { |ts| Group::new(Delimiter::Brace, ts) } --)); -- --fn symbol_leading_ws(input: Cursor) -> PResult { -- symbol(skip_whitespace(input)) --} -- --fn symbol(input: Cursor) -> PResult { -- let raw = input.starts_with("r#"); -- let rest = input.advance((raw as usize) << 1); -- -- let (rest, sym) = symbol_not_raw(rest)?; -- -- if !raw { -- let ident = crate::Ident::new(sym, crate::Span::call_site()); -- return Ok((rest, ident.into())); -- } -- -- if sym == "_" { -- return Err(LexError); -- } -- -- let ident = crate::Ident::_new_raw(sym, crate::Span::call_site()); -- Ok((rest, ident.into())) --} -- --fn symbol_not_raw(input: Cursor) -> PResult<&str> { -- let mut chars = input.char_indices(); -- -- match chars.next() { -- Some((_, ch)) if is_ident_start(ch) => {} -- _ => return Err(LexError), -- } -- -- let mut end = input.len(); -- for (i, ch) in chars { -- if !is_ident_continue(ch) { -- end = i; -- break; -- } -- } -- -- Ok((input.advance(end), &input.rest[..end])) --} -- --fn literal(input: Cursor) -> PResult { -- let input_no_ws = skip_whitespace(input); -- -- match literal_nocapture(input_no_ws) { -- Ok((a, ())) => { -- let start = input.len() - input_no_ws.len(); -- let len = input_no_ws.len() - a.len(); -- let end = start + len; -- Ok((a, Literal::_new(input.rest[start..end].to_string()))) -- } -- Err(LexError) => Err(LexError), -+ Display::fmt(&self.text, f) - } - } - --named!(literal_nocapture -> (), alt!( -- string -- | -- byte_string -- | -- byte -- | -- character -- | -- float -- | -- int --)); -- --named!(string -> (), alt!( -- quoted_string -- | -- preceded!( -- punct!("r"), -- raw_string -- ) => { |_| () } --)); -- --named!(quoted_string -> (), do_parse!( -- punct!("\"") >> -- cooked_string >> -- tag!("\"") >> -- option!(symbol_not_raw) >> -- (()) --)); -- --fn cooked_string(input: Cursor) -> PResult<()> { -- let mut chars = input.char_indices().peekable(); -- while let Some((byte_offset, ch)) = chars.next() { -- match ch { -- '"' => { -- return Ok((input.advance(byte_offset), ())); -- } -- '\r' => { -- if let Some((_, '\n')) = chars.next() { -- // ... -- } else { -- break; -- } -- } -- '\\' => match chars.next() { -- Some((_, 'x')) => { -- if !backslash_x_char(&mut chars) { -- break; -- } -- } -- Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\')) -- | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {} -- Some((_, 'u')) => { -- if !backslash_u(&mut chars) { -- break; -- } -- } -- Some((_, '\n')) | Some((_, '\r')) => { -- while let Some(&(_, ch)) = chars.peek() { -- if ch.is_whitespace() { -- chars.next(); -- } else { -- break; -- } -- } -- } -- _ => break, -- }, -- _ch => {} -- } -- } -- Err(LexError) --} -- --named!(byte_string -> (), alt!( -- delimited!( -- punct!("b\""), -- cooked_byte_string, -- tag!("\"") -- ) => { |_| () } -- | -- preceded!( -- punct!("br"), -- raw_string -- ) => { |_| () } --)); -- --fn cooked_byte_string(mut input: Cursor) -> PResult<()> { -- let mut bytes = input.bytes().enumerate(); -- 'outer: while let Some((offset, b)) = bytes.next() { -- match b { -- b'"' => { -- return Ok((input.advance(offset), ())); -- } -- b'\r' => { -- if let Some((_, b'\n')) = bytes.next() { -- // ... -- } else { -- break; -- } -- } -- b'\\' => match bytes.next() { -- Some((_, b'x')) => { -- if !backslash_x_byte(&mut bytes) { -- break; -- } -- } -- Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\')) -- | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {} -- Some((newline, b'\n')) | Some((newline, b'\r')) => { -- let rest = input.advance(newline + 1); -- for (offset, ch) in rest.char_indices() { -- if !ch.is_whitespace() { -- input = rest.advance(offset); -- bytes = input.bytes().enumerate(); -- continue 'outer; -- } -- } -- break; -- } -- _ => break, -- }, -- b if b < 0x80 => {} -- _ => break, -- } -- } -- Err(LexError) --} -- --fn raw_string(input: Cursor) -> PResult<()> { -- let mut chars = input.char_indices(); -- let mut n = 0; -- while let Some((byte_offset, ch)) = chars.next() { -- match ch { -- '"' => { -- n = byte_offset; -- break; -- } -- '#' => {} -- _ => return Err(LexError), -- } -- } -- for (byte_offset, ch) in chars { -- match ch { -- '"' if input.advance(byte_offset + 1).starts_with(&input.rest[..n]) => { -- let rest = input.advance(byte_offset + 1 + n); -- return Ok((rest, ())); -- } -- '\r' => {} -- _ => {} -- } -- } -- Err(LexError) --} -- --named!(byte -> (), do_parse!( -- punct!("b") >> -- tag!("'") >> -- cooked_byte >> -- tag!("'") >> -- (()) --)); -- --fn cooked_byte(input: Cursor) -> PResult<()> { -- let mut bytes = input.bytes().enumerate(); -- let ok = match bytes.next().map(|(_, b)| b) { -- Some(b'\\') => match bytes.next().map(|(_, b)| b) { -- Some(b'x') => backslash_x_byte(&mut bytes), -- Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'') -- | Some(b'"') => true, -- _ => false, -- }, -- b => b.is_some(), -- }; -- if ok { -- match bytes.next() { -- Some((offset, _)) => { -- if input.chars().as_str().is_char_boundary(offset) { -- Ok((input.advance(offset), ())) -- } else { -- Err(LexError) -- } -- } -- None => Ok((input.advance(input.len()), ())), -- } -- } else { -- Err(LexError) -- } --} -- --named!(character -> (), do_parse!( -- punct!("'") >> -- cooked_char >> -- tag!("'") >> -- (()) --)); -- --fn cooked_char(input: Cursor) -> PResult<()> { -- let mut chars = input.char_indices(); -- let ok = match chars.next().map(|(_, ch)| ch) { -- Some('\\') => match chars.next().map(|(_, ch)| ch) { -- Some('x') => backslash_x_char(&mut chars), -- Some('u') => backslash_u(&mut chars), -- Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => { -- true -- } -- _ => false, -- }, -- ch => ch.is_some(), -- }; -- if ok { -- match chars.next() { -- Some((idx, _)) => Ok((input.advance(idx), ())), -- None => Ok((input.advance(input.len()), ())), -- } -- } else { -- Err(LexError) -+impl Debug for Literal { -+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { -+ let mut debug = fmt.debug_struct("Literal"); -+ debug.field("lit", &format_args!("{}", self.text)); -+ debug_span_field_if_nontrivial(&mut debug, self.span); -+ debug.finish() - } - } -- --macro_rules! next_ch { -- ($chars:ident @ $pat:pat $(| $rest:pat)*) => { -- match $chars.next() { -- Some((_, ch)) => match ch { -- $pat $(| $rest)* => ch, -- _ => return false, -- }, -- None => return false -- } -- }; --} -- --fn backslash_x_char(chars: &mut I) -> bool --where -- I: Iterator, --{ -- next_ch!(chars @ '0'..='7'); -- next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); -- true --} -- --fn backslash_x_byte(chars: &mut I) -> bool --where -- I: Iterator, --{ -- next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); -- next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); -- true --} -- --fn backslash_u(chars: &mut I) -> bool --where -- I: Iterator, --{ -- next_ch!(chars @ '{'); -- next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); -- loop { -- let c = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F' | '_' | '}'); -- if c == '}' { -- return true; -- } -- } --} -- --fn float(input: Cursor) -> PResult<()> { -- let (mut rest, ()) = float_digits(input)?; -- if let Some(ch) = rest.chars().next() { -- if is_ident_start(ch) { -- rest = symbol_not_raw(rest)?.0; -- } -- } -- word_break(rest) --} -- --fn float_digits(input: Cursor) -> PResult<()> { -- let mut chars = input.chars().peekable(); -- match chars.next() { -- Some(ch) if ch >= '0' && ch <= '9' => {} -- _ => return Err(LexError), -- } -- -- let mut len = 1; -- let mut has_dot = false; -- let mut has_exp = false; -- while let Some(&ch) = chars.peek() { -- match ch { -- '0'..='9' | '_' => { -- chars.next(); -- len += 1; -- } -- '.' => { -- if has_dot { -- break; -- } -- chars.next(); -- if chars -- .peek() -- .map(|&ch| ch == '.' || is_ident_start(ch)) -- .unwrap_or(false) -- { -- return Err(LexError); -- } -- len += 1; -- has_dot = true; -- } -- 'e' | 'E' => { -- chars.next(); -- len += 1; -- has_exp = true; -- break; -- } -- _ => break, -- } -- } -- -- let rest = input.advance(len); -- if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) { -- return Err(LexError); -- } -- -- if has_exp { -- let mut has_exp_value = false; -- while let Some(&ch) = chars.peek() { -- match ch { -- '+' | '-' => { -- if has_exp_value { -- break; -- } -- chars.next(); -- len += 1; -- } -- '0'..='9' => { -- chars.next(); -- len += 1; -- has_exp_value = true; -- } -- '_' => { -- chars.next(); -- len += 1; -- } -- _ => break, -- } -- } -- if !has_exp_value { -- return Err(LexError); -- } -- } -- -- Ok((input.advance(len), ())) --} -- --fn int(input: Cursor) -> PResult<()> { -- let (mut rest, ()) = digits(input)?; -- if let Some(ch) = rest.chars().next() { -- if is_ident_start(ch) { -- rest = symbol_not_raw(rest)?.0; -- } -- } -- word_break(rest) --} -- --fn digits(mut input: Cursor) -> PResult<()> { -- let base = if input.starts_with("0x") { -- input = input.advance(2); -- 16 -- } else if input.starts_with("0o") { -- input = input.advance(2); -- 8 -- } else if input.starts_with("0b") { -- input = input.advance(2); -- 2 -- } else { -- 10 -- }; -- -- let mut len = 0; -- let mut empty = true; -- for b in input.bytes() { -- let digit = match b { -- b'0'..=b'9' => (b - b'0') as u64, -- b'a'..=b'f' => 10 + (b - b'a') as u64, -- b'A'..=b'F' => 10 + (b - b'A') as u64, -- b'_' => { -- if empty && base == 10 { -- return Err(LexError); -- } -- len += 1; -- continue; -- } -- _ => break, -- }; -- if digit >= base { -- return Err(LexError); -- } -- len += 1; -- empty = false; -- } -- if empty { -- Err(LexError) -- } else { -- Ok((input.advance(len), ())) -- } --} -- --fn op(input: Cursor) -> PResult { -- let input = skip_whitespace(input); -- match op_char(input) { -- Ok((rest, '\'')) => { -- symbol(rest)?; -- Ok((rest, Punct::new('\'', Spacing::Joint))) -- } -- Ok((rest, ch)) => { -- let kind = match op_char(rest) { -- Ok(_) => Spacing::Joint, -- Err(LexError) => Spacing::Alone, -- }; -- Ok((rest, Punct::new(ch, kind))) -- } -- Err(LexError) => Err(LexError), -- } --} -- --fn op_char(input: Cursor) -> PResult { -- if input.starts_with("//") || input.starts_with("/*") { -- // Do not accept `/` of a comment as an op. -- return Err(LexError); -- } -- -- let mut chars = input.chars(); -- let first = match chars.next() { -- Some(ch) => ch, -- None => { -- return Err(LexError); -- } -- }; -- let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; -- if recognized.contains(first) { -- Ok((input.advance(first.len_utf8()), first)) -- } else { -- Err(LexError) -- } --} -- --fn doc_comment(input: Cursor) -> PResult> { -- let mut trees = Vec::new(); -- let (rest, ((comment, inner), span)) = spanned(input, doc_comment_contents)?; -- trees.push(TokenTree::Punct(Punct::new('#', Spacing::Alone))); -- if inner { -- trees.push(Punct::new('!', Spacing::Alone).into()); -- } -- let mut stream = vec![ -- TokenTree::Ident(crate::Ident::new("doc", span)), -- TokenTree::Punct(Punct::new('=', Spacing::Alone)), -- TokenTree::Literal(crate::Literal::string(comment)), -- ]; -- for tt in stream.iter_mut() { -- tt.set_span(span); -- } -- let group = Group::new(Delimiter::Bracket, stream.into_iter().collect()); -- trees.push(crate::Group::_new_stable(group).into()); -- for tt in trees.iter_mut() { -- tt.set_span(span); -- } -- Ok((rest, trees)) --} -- --named!(doc_comment_contents -> (&str, bool), alt!( -- do_parse!( -- punct!("//!") >> -- s: take_until_newline_or_eof!() >> -- ((s, true)) -- ) -- | -- do_parse!( -- option!(whitespace) >> -- peek!(tag!("/*!")) >> -- s: block_comment >> -- ((s, true)) -- ) -- | -- do_parse!( -- punct!("///") >> -- not!(tag!("/")) >> -- s: take_until_newline_or_eof!() >> -- ((s, false)) -- ) -- | -- do_parse!( -- option!(whitespace) >> -- peek!(tuple!(tag!("/**"), not!(tag!("*")))) >> -- s: block_comment >> -- ((s, false)) -- ) --)); -diff --git a/third_party/rust/proc-macro2/src/lib.rs b/third_party/rust/proc-macro2/src/lib.rs ---- a/third_party/rust/proc-macro2/src/lib.rs -+++ b/third_party/rust/proc-macro2/src/lib.rs -@@ -73,37 +73,44 @@ - //! - //! # Thread-Safety - //! - //! Most types in this crate are `!Sync` because the underlying compiler - //! types make use of thread-local memory, meaning they cannot be accessed from - //! a different thread. - - // Proc-macro2 types in rustdoc of other crates get linked to here. --#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.5")] -+#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.20")] - #![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))] - #![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))] -+#![allow(clippy::needless_doctest_main)] - - #[cfg(use_proc_macro)] - extern crate proc_macro; - - use std::cmp::Ordering; --use std::fmt; -+use std::fmt::{self, Debug, Display}; - use std::hash::{Hash, Hasher}; - use std::iter::FromIterator; - use std::marker; - use std::ops::RangeBounds; - #[cfg(procmacro2_semver_exempt)] - use std::path::PathBuf; - use std::rc::Rc; - use std::str::FromStr; - --#[macro_use] --mod strnom; --mod fallback; -+mod parse; -+ -+#[cfg(wrap_proc_macro)] -+mod detection; -+ -+// Public for proc_macro2::fallback::force() and unforce(), but those are quite -+// a niche use case so we omit it from rustdoc. -+#[doc(hidden)] -+pub mod fallback; - - #[cfg(not(wrap_proc_macro))] - use crate::fallback as imp; - #[path = "wrapper.rs"] - #[cfg(wrap_proc_macro)] - mod imp; - - /// An abstract stream of tokens, or more concretely a sequence of token trees. -@@ -223,32 +230,32 @@ impl FromIterator for Token - TokenStream::_new(streams.into_iter().map(|i| i.inner).collect()) - } - } - - /// Prints the token stream as a string that is supposed to be losslessly - /// convertible back into the same token stream (modulo spans), except for - /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative - /// numeric literals. --impl fmt::Display for TokenStream { -+impl Display for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Display::fmt(&self.inner, f) - } - } - - /// Prints token in a form convenient for debugging. --impl fmt::Debug for TokenStream { -+impl Debug for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Debug::fmt(&self.inner, f) - } - } - --impl fmt::Debug for LexError { -+impl Debug for LexError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Debug::fmt(&self.inner, f) - } - } - - /// The source file of a given `Span`. - /// - /// This type is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] - #[derive(Clone, PartialEq, Eq)] -@@ -286,19 +293,19 @@ impl SourceFile { - /// Returns `true` if this source file is a real source file, and not - /// generated by an external macro's expansion. - pub fn is_real(&self) -> bool { - self.inner.is_real() - } - } - - #[cfg(procmacro2_semver_exempt)] --impl fmt::Debug for SourceFile { -+impl Debug for SourceFile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Debug::fmt(&self.inner, f) - } - } - - /// A line-column pair representing the start or end of a `Span`. - /// - /// This type is semver exempt and not exposed by default. - #[cfg(span_locations)] - #[derive(Copy, Clone, Debug, PartialEq, Eq)] -@@ -306,16 +313,32 @@ pub struct LineColumn { - /// The 1-indexed line in the source file on which the span starts or ends - /// (inclusive). - pub line: usize, - /// The 0-indexed column (in UTF-8 characters) in the source file on which - /// the span starts or ends (inclusive). - pub column: usize, - } - -+#[cfg(span_locations)] -+impl Ord for LineColumn { -+ fn cmp(&self, other: &Self) -> Ordering { -+ self.line -+ .cmp(&other.line) -+ .then(self.column.cmp(&other.column)) -+ } -+} -+ -+#[cfg(span_locations)] -+impl PartialOrd for LineColumn { -+ fn partial_cmp(&self, other: &Self) -> Option { -+ Some(self.cmp(other)) -+ } -+} -+ - /// A region of source code, along with macro expansion information. - #[derive(Copy, Clone)] - pub struct Span { - inner: imp::Span, - _marker: marker::PhantomData>, - } - - impl Span { -@@ -337,38 +360,42 @@ impl Span { - /// - /// Identifiers created with this span will be resolved as if they were - /// written directly at the macro call location (call-site hygiene) and - /// other code at the macro call site will be able to refer to them as well. - pub fn call_site() -> Span { - Span::_new(imp::Span::call_site()) - } - -+ /// The span located at the invocation of the procedural macro, but with -+ /// local variables, labels, and `$crate` resolved at the definition site -+ /// of the macro. This is the same hygiene behavior as `macro_rules`. -+ /// -+ /// This function requires Rust 1.45 or later. -+ #[cfg(hygiene)] -+ pub fn mixed_site() -> Span { -+ Span::_new(imp::Span::mixed_site()) -+ } -+ - /// A span that resolves at the macro definition site. - /// - /// This method is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] - pub fn def_site() -> Span { - Span::_new(imp::Span::def_site()) - } - - /// Creates a new span with the same line/column information as `self` but - /// that resolves symbols as though it were at `other`. -- /// -- /// This method is semver exempt and not exposed by default. -- #[cfg(procmacro2_semver_exempt)] - pub fn resolved_at(&self, other: Span) -> Span { - Span::_new(self.inner.resolved_at(other.inner)) - } - - /// Creates a new span with the same name resolution behavior as `self` but - /// with the line/column information of `other`. -- /// -- /// This method is semver exempt and not exposed by default. -- #[cfg(procmacro2_semver_exempt)] - pub fn located_at(&self, other: Span) -> Span { - Span::_new(self.inner.located_at(other.inner)) - } - - /// Convert `proc_macro2::Span` to `proc_macro::Span`. - /// - /// This method is available when building with a nightly compiler, or when - /// building with rustc 1.29+ *without* semver exempt features. -@@ -434,19 +461,19 @@ impl Span { - /// This method is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] - pub fn eq(&self, other: &Span) -> bool { - self.inner.eq(&other.inner) - } - } - - /// Prints a span in a form convenient for debugging. --impl fmt::Debug for Span { -+impl Debug for Span { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Debug::fmt(&self.inner, f) - } - } - - /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`). - #[derive(Clone)] - pub enum TokenTree { - /// A token stream surrounded by bracket delimiters. - Group(Group), -@@ -457,35 +484,35 @@ pub enum TokenTree { - /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc. - Literal(Literal), - } - - impl TokenTree { - /// Returns the span of this tree, delegating to the `span` method of - /// the contained token or a delimited stream. - pub fn span(&self) -> Span { -- match *self { -- TokenTree::Group(ref t) => t.span(), -- TokenTree::Ident(ref t) => t.span(), -- TokenTree::Punct(ref t) => t.span(), -- TokenTree::Literal(ref t) => t.span(), -+ match self { -+ TokenTree::Group(t) => t.span(), -+ TokenTree::Ident(t) => t.span(), -+ TokenTree::Punct(t) => t.span(), -+ TokenTree::Literal(t) => t.span(), - } - } - - /// Configures the span for *only this token*. - /// - /// Note that if this token is a `Group` then this method will not configure - /// the span of each of the internal tokens, this will simply delegate to - /// the `set_span` method of each variant. - pub fn set_span(&mut self, span: Span) { -- match *self { -- TokenTree::Group(ref mut t) => t.set_span(span), -- TokenTree::Ident(ref mut t) => t.set_span(span), -- TokenTree::Punct(ref mut t) => t.set_span(span), -- TokenTree::Literal(ref mut t) => t.set_span(span), -+ match self { -+ TokenTree::Group(t) => t.set_span(span), -+ TokenTree::Ident(t) => t.set_span(span), -+ TokenTree::Punct(t) => t.set_span(span), -+ TokenTree::Literal(t) => t.set_span(span), - } - } - } - - impl From for TokenTree { - fn from(g: Group) -> TokenTree { - TokenTree::Group(g) - } -@@ -508,42 +535,42 @@ impl From for TokenTree { - TokenTree::Literal(g) - } - } - - /// Prints the token tree as a string that is supposed to be losslessly - /// convertible back into the same token tree (modulo spans), except for - /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative - /// numeric literals. --impl fmt::Display for TokenTree { -+impl Display for TokenTree { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- match *self { -- TokenTree::Group(ref t) => t.fmt(f), -- TokenTree::Ident(ref t) => t.fmt(f), -- TokenTree::Punct(ref t) => t.fmt(f), -- TokenTree::Literal(ref t) => t.fmt(f), -+ match self { -+ TokenTree::Group(t) => Display::fmt(t, f), -+ TokenTree::Ident(t) => Display::fmt(t, f), -+ TokenTree::Punct(t) => Display::fmt(t, f), -+ TokenTree::Literal(t) => Display::fmt(t, f), - } - } - } - - /// Prints token tree in a form convenient for debugging. --impl fmt::Debug for TokenTree { -+impl Debug for TokenTree { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // Each of these has the name in the struct type in the derived debug, - // so don't bother with an extra layer of indirection -- match *self { -- TokenTree::Group(ref t) => t.fmt(f), -- TokenTree::Ident(ref t) => { -+ match self { -+ TokenTree::Group(t) => Debug::fmt(t, f), -+ TokenTree::Ident(t) => { - let mut debug = f.debug_struct("Ident"); - debug.field("sym", &format_args!("{}", t)); - imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner); - debug.finish() - } -- TokenTree::Punct(ref t) => t.fmt(f), -- TokenTree::Literal(ref t) => t.fmt(f), -+ TokenTree::Punct(t) => Debug::fmt(t, f), -+ TokenTree::Literal(t) => Debug::fmt(t, f), - } - } - } - - /// A delimited token stream. - /// - /// A `Group` internally contains a `TokenStream` which is surrounded by - /// `Delimiter`s. -@@ -646,25 +673,25 @@ impl Group { - pub fn set_span(&mut self, span: Span) { - self.inner.set_span(span.inner) - } - } - - /// Prints the group as a string that should be losslessly convertible back - /// into the same group (modulo spans), except for possibly `TokenTree::Group`s - /// with `Delimiter::None` delimiters. --impl fmt::Display for Group { -+impl Display for Group { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { -- fmt::Display::fmt(&self.inner, formatter) -+ Display::fmt(&self.inner, formatter) - } - } - --impl fmt::Debug for Group { -+impl Debug for Group { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { -- fmt::Debug::fmt(&self.inner, formatter) -+ Debug::fmt(&self.inner, formatter) - } - } - - /// An `Punct` is an single punctuation character like `+`, `-` or `#`. - /// - /// Multicharacter operators like `+=` are represented as two instances of - /// `Punct` with different forms of `Spacing` returned. - #[derive(Clone)] -@@ -725,23 +752,23 @@ impl Punct { - /// Configure the span for this punctuation character. - pub fn set_span(&mut self, span: Span) { - self.span = span; - } - } - - /// Prints the punctuation character as a string that should be losslessly - /// convertible back into the same character. --impl fmt::Display for Punct { -+impl Display for Punct { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.op.fmt(f) -+ Display::fmt(&self.op, f) - } - } - --impl fmt::Debug for Punct { -+impl Debug for Punct { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut debug = fmt.debug_struct("Punct"); - debug.field("op", &self.op); - debug.field("spacing", &self.spacing); - imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner); - debug.finish() - } - } -@@ -915,25 +942,25 @@ impl Ord for Ident { - impl Hash for Ident { - fn hash(&self, hasher: &mut H) { - self.to_string().hash(hasher) - } - } - - /// Prints the identifier as a string that should be losslessly convertible back - /// into the same identifier. --impl fmt::Display for Ident { -+impl Display for Ident { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Display::fmt(&self.inner, f) - } - } - --impl fmt::Debug for Ident { -+impl Debug for Ident { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Debug::fmt(&self.inner, f) - } - } - - /// A literal string (`"hello"`), byte string (`b"hello"`), character (`'a'`), - /// byte character (`b'a'`), an integer or floating point number with or without - /// a suffix (`1`, `1u8`, `2.3`, `2.3f32`). - /// - /// Boolean literals like `true` and `false` do not belong here, they are -@@ -1135,36 +1162,36 @@ impl Literal { - /// nightly compiler, this method will always return `None`. - /// - /// [`proc_macro::Literal::subspan`]: https://doc.rust-lang.org/proc_macro/struct.Literal.html#method.subspan - pub fn subspan>(&self, range: R) -> Option { - self.inner.subspan(range).map(Span::_new) - } - } - --impl fmt::Debug for Literal { -+impl Debug for Literal { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Debug::fmt(&self.inner, f) - } - } - --impl fmt::Display for Literal { -+impl Display for Literal { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Display::fmt(&self.inner, f) - } - } - - /// Public implementation details for the `TokenStream` type, such as iterators. - pub mod token_stream { -- use std::fmt; -+ use crate::{imp, TokenTree}; -+ use std::fmt::{self, Debug}; - use std::marker; - use std::rc::Rc; - - pub use crate::TokenStream; -- use crate::{imp, TokenTree}; - - /// An iterator over `TokenStream`'s `TokenTree`s. - /// - /// The iteration is "shallow", e.g. the iterator doesn't recurse into - /// delimited groups, and returns whole groups as token trees. - #[derive(Clone)] - pub struct IntoIter { - inner: imp::TokenTreeIter, -@@ -1174,19 +1201,19 @@ pub mod token_stream { - impl Iterator for IntoIter { - type Item = TokenTree; - - fn next(&mut self) -> Option { - self.inner.next() - } - } - -- impl fmt::Debug for IntoIter { -+ impl Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -- self.inner.fmt(f) -+ Debug::fmt(&self.inner, f) - } - } - - impl IntoIterator for TokenStream { - type Item = TokenTree; - type IntoIter = IntoIter; - - fn into_iter(self) -> IntoIter { -diff --git a/third_party/rust/proc-macro2/src/parse.rs b/third_party/rust/proc-macro2/src/parse.rs -new file mode 100644 ---- /dev/null -+++ b/third_party/rust/proc-macro2/src/parse.rs -@@ -0,0 +1,791 @@ -+use crate::fallback::{ -+ is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream, -+}; -+use crate::{Delimiter, Punct, Spacing, TokenTree}; -+use std::str::{Bytes, CharIndices, Chars}; -+use unicode_xid::UnicodeXID; -+ -+#[derive(Copy, Clone, Eq, PartialEq)] -+pub(crate) struct Cursor<'a> { -+ pub rest: &'a str, -+ #[cfg(span_locations)] -+ pub off: u32, -+} -+ -+impl<'a> Cursor<'a> { -+ fn advance(&self, bytes: usize) -> Cursor<'a> { -+ let (_front, rest) = self.rest.split_at(bytes); -+ Cursor { -+ rest, -+ #[cfg(span_locations)] -+ off: self.off + _front.chars().count() as u32, -+ } -+ } -+ -+ fn starts_with(&self, s: &str) -> bool { -+ self.rest.starts_with(s) -+ } -+ -+ pub(crate) fn is_empty(&self) -> bool { -+ self.rest.is_empty() -+ } -+ -+ fn len(&self) -> usize { -+ self.rest.len() -+ } -+ -+ fn as_bytes(&self) -> &'a [u8] { -+ self.rest.as_bytes() -+ } -+ -+ fn bytes(&self) -> Bytes<'a> { -+ self.rest.bytes() -+ } -+ -+ fn chars(&self) -> Chars<'a> { -+ self.rest.chars() -+ } -+ -+ fn char_indices(&self) -> CharIndices<'a> { -+ self.rest.char_indices() -+ } -+ -+ fn parse(&self, tag: &str) -> Result, LexError> { -+ if self.starts_with(tag) { -+ Ok(self.advance(tag.len())) -+ } else { -+ Err(LexError) -+ } -+ } -+} -+ -+type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>; -+ -+fn skip_whitespace(input: Cursor) -> Cursor { -+ let mut s = input; -+ -+ while !s.is_empty() { -+ let byte = s.as_bytes()[0]; -+ if byte == b'/' { -+ if s.starts_with("//") -+ && (!s.starts_with("///") || s.starts_with("////")) -+ && !s.starts_with("//!") -+ { -+ let (cursor, _) = take_until_newline_or_eof(s); -+ s = cursor; -+ continue; -+ } else if s.starts_with("/**/") { -+ s = s.advance(4); -+ continue; -+ } else if s.starts_with("/*") -+ && (!s.starts_with("/**") || s.starts_with("/***")) -+ && !s.starts_with("/*!") -+ { -+ match block_comment(s) { -+ Ok((rest, _)) => { -+ s = rest; -+ continue; -+ } -+ Err(LexError) => return s, -+ } -+ } -+ } -+ match byte { -+ b' ' | 0x09..=0x0d => { -+ s = s.advance(1); -+ continue; -+ } -+ b if b <= 0x7f => {} -+ _ => { -+ let ch = s.chars().next().unwrap(); -+ if is_whitespace(ch) { -+ s = s.advance(ch.len_utf8()); -+ continue; -+ } -+ } -+ } -+ return s; -+ } -+ s -+} -+ -+fn block_comment(input: Cursor) -> PResult<&str> { -+ if !input.starts_with("/*") { -+ return Err(LexError); -+ } -+ -+ let mut depth = 0; -+ let bytes = input.as_bytes(); -+ let mut i = 0; -+ let upper = bytes.len() - 1; -+ -+ while i < upper { -+ if bytes[i] == b'/' && bytes[i + 1] == b'*' { -+ depth += 1; -+ i += 1; // eat '*' -+ } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { -+ depth -= 1; -+ if depth == 0 { -+ return Ok((input.advance(i + 2), &input.rest[..i + 2])); -+ } -+ i += 1; // eat '/' -+ } -+ i += 1; -+ } -+ -+ Err(LexError) -+} -+ -+fn is_whitespace(ch: char) -> bool { -+ // Rust treats left-to-right mark and right-to-left mark as whitespace -+ ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' -+} -+ -+fn word_break(input: Cursor) -> Result { -+ match input.chars().next() { -+ Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError), -+ Some(_) | None => Ok(input), -+ } -+} -+ -+pub(crate) fn token_stream(mut input: Cursor) -> PResult { -+ let mut trees = Vec::new(); -+ let mut stack = Vec::new(); -+ -+ loop { -+ input = skip_whitespace(input); -+ -+ if let Ok((rest, tt)) = doc_comment(input) { -+ trees.extend(tt); -+ input = rest; -+ continue; -+ } -+ -+ #[cfg(span_locations)] -+ let lo = input.off; -+ -+ let first = match input.bytes().next() { -+ Some(first) => first, -+ None => break, -+ }; -+ -+ if let Some(open_delimiter) = match first { -+ b'(' => Some(Delimiter::Parenthesis), -+ b'[' => Some(Delimiter::Bracket), -+ b'{' => Some(Delimiter::Brace), -+ _ => None, -+ } { -+ input = input.advance(1); -+ let frame = (open_delimiter, trees); -+ #[cfg(span_locations)] -+ let frame = (lo, frame); -+ stack.push(frame); -+ trees = Vec::new(); -+ } else if let Some(close_delimiter) = match first { -+ b')' => Some(Delimiter::Parenthesis), -+ b']' => Some(Delimiter::Bracket), -+ b'}' => Some(Delimiter::Brace), -+ _ => None, -+ } { -+ input = input.advance(1); -+ let frame = stack.pop().ok_or(LexError)?; -+ #[cfg(span_locations)] -+ let (lo, frame) = frame; -+ let (open_delimiter, outer) = frame; -+ if open_delimiter != close_delimiter { -+ return Err(LexError); -+ } -+ let mut g = Group::new(open_delimiter, TokenStream { inner: trees }); -+ g.set_span(Span { -+ #[cfg(span_locations)] -+ lo, -+ #[cfg(span_locations)] -+ hi: input.off, -+ }); -+ trees = outer; -+ trees.push(TokenTree::Group(crate::Group::_new_stable(g))); -+ } else { -+ let (rest, mut tt) = leaf_token(input)?; -+ tt.set_span(crate::Span::_new_stable(Span { -+ #[cfg(span_locations)] -+ lo, -+ #[cfg(span_locations)] -+ hi: rest.off, -+ })); -+ trees.push(tt); -+ input = rest; -+ } -+ } -+ -+ if stack.is_empty() { -+ Ok((input, TokenStream { inner: trees })) -+ } else { -+ Err(LexError) -+ } -+} -+ -+fn leaf_token(input: Cursor) -> PResult { -+ if let Ok((input, l)) = literal(input) { -+ // must be parsed before ident -+ Ok((input, TokenTree::Literal(crate::Literal::_new_stable(l)))) -+ } else if let Ok((input, p)) = op(input) { -+ Ok((input, TokenTree::Punct(p))) -+ } else if let Ok((input, i)) = ident(input) { -+ Ok((input, TokenTree::Ident(i))) -+ } else { -+ Err(LexError) -+ } -+} -+ -+fn ident(input: Cursor) -> PResult { -+ let raw = input.starts_with("r#"); -+ let rest = input.advance((raw as usize) << 1); -+ -+ let (rest, sym) = ident_not_raw(rest)?; -+ -+ if !raw { -+ let ident = crate::Ident::new(sym, crate::Span::call_site()); -+ return Ok((rest, ident)); -+ } -+ -+ if sym == "_" { -+ return Err(LexError); -+ } -+ -+ let ident = crate::Ident::_new_raw(sym, crate::Span::call_site()); -+ Ok((rest, ident)) -+} -+ -+fn ident_not_raw(input: Cursor) -> PResult<&str> { -+ let mut chars = input.char_indices(); -+ -+ match chars.next() { -+ Some((_, ch)) if is_ident_start(ch) => {} -+ _ => return Err(LexError), -+ } -+ -+ let mut end = input.len(); -+ for (i, ch) in chars { -+ if !is_ident_continue(ch) { -+ end = i; -+ break; -+ } -+ } -+ -+ Ok((input.advance(end), &input.rest[..end])) -+} -+ -+fn literal(input: Cursor) -> PResult { -+ match literal_nocapture(input) { -+ Ok(a) => { -+ let end = input.len() - a.len(); -+ Ok((a, Literal::_new(input.rest[..end].to_string()))) -+ } -+ Err(LexError) => Err(LexError), -+ } -+} -+ -+fn literal_nocapture(input: Cursor) -> Result { -+ if let Ok(ok) = string(input) { -+ Ok(ok) -+ } else if let Ok(ok) = byte_string(input) { -+ Ok(ok) -+ } else if let Ok(ok) = byte(input) { -+ Ok(ok) -+ } else if let Ok(ok) = character(input) { -+ Ok(ok) -+ } else if let Ok(ok) = float(input) { -+ Ok(ok) -+ } else if let Ok(ok) = int(input) { -+ Ok(ok) -+ } else { -+ Err(LexError) -+ } -+} -+ -+fn literal_suffix(input: Cursor) -> Cursor { -+ match ident_not_raw(input) { -+ Ok((input, _)) => input, -+ Err(LexError) => input, -+ } -+} -+ -+fn string(input: Cursor) -> Result { -+ if let Ok(input) = input.parse("\"") { -+ cooked_string(input) -+ } else if let Ok(input) = input.parse("r") { -+ raw_string(input) -+ } else { -+ Err(LexError) -+ } -+} -+ -+fn cooked_string(input: Cursor) -> Result { -+ let mut chars = input.char_indices().peekable(); -+ -+ while let Some((i, ch)) = chars.next() { -+ match ch { -+ '"' => { -+ let input = input.advance(i + 1); -+ return Ok(literal_suffix(input)); -+ } -+ '\r' => { -+ if let Some((_, '\n')) = chars.next() { -+ // ... -+ } else { -+ break; -+ } -+ } -+ '\\' => match chars.next() { -+ Some((_, 'x')) => { -+ if !backslash_x_char(&mut chars) { -+ break; -+ } -+ } -+ Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\')) -+ | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {} -+ Some((_, 'u')) => { -+ if !backslash_u(&mut chars) { -+ break; -+ } -+ } -+ Some((_, '\n')) | Some((_, '\r')) => { -+ while let Some(&(_, ch)) = chars.peek() { -+ if ch.is_whitespace() { -+ chars.next(); -+ } else { -+ break; -+ } -+ } -+ } -+ _ => break, -+ }, -+ _ch => {} -+ } -+ } -+ Err(LexError) -+} -+ -+fn byte_string(input: Cursor) -> Result { -+ if let Ok(input) = input.parse("b\"") { -+ cooked_byte_string(input) -+ } else if let Ok(input) = input.parse("br") { -+ raw_string(input) -+ } else { -+ Err(LexError) -+ } -+} -+ -+fn cooked_byte_string(mut input: Cursor) -> Result { -+ let mut bytes = input.bytes().enumerate(); -+ 'outer: while let Some((offset, b)) = bytes.next() { -+ match b { -+ b'"' => { -+ let input = input.advance(offset + 1); -+ return Ok(literal_suffix(input)); -+ } -+ b'\r' => { -+ if let Some((_, b'\n')) = bytes.next() { -+ // ... -+ } else { -+ break; -+ } -+ } -+ b'\\' => match bytes.next() { -+ Some((_, b'x')) => { -+ if !backslash_x_byte(&mut bytes) { -+ break; -+ } -+ } -+ Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\')) -+ | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {} -+ Some((newline, b'\n')) | Some((newline, b'\r')) => { -+ let rest = input.advance(newline + 1); -+ for (offset, ch) in rest.char_indices() { -+ if !ch.is_whitespace() { -+ input = rest.advance(offset); -+ bytes = input.bytes().enumerate(); -+ continue 'outer; -+ } -+ } -+ break; -+ } -+ _ => break, -+ }, -+ b if b < 0x80 => {} -+ _ => break, -+ } -+ } -+ Err(LexError) -+} -+ -+fn raw_string(input: Cursor) -> Result { -+ let mut chars = input.char_indices(); -+ let mut n = 0; -+ while let Some((i, ch)) = chars.next() { -+ match ch { -+ '"' => { -+ n = i; -+ break; -+ } -+ '#' => {} -+ _ => return Err(LexError), -+ } -+ } -+ for (i, ch) in chars { -+ match ch { -+ '"' if input.rest[i + 1..].starts_with(&input.rest[..n]) => { -+ let rest = input.advance(i + 1 + n); -+ return Ok(literal_suffix(rest)); -+ } -+ '\r' => {} -+ _ => {} -+ } -+ } -+ Err(LexError) -+} -+ -+fn byte(input: Cursor) -> Result { -+ let input = input.parse("b'")?; -+ let mut bytes = input.bytes().enumerate(); -+ let ok = match bytes.next().map(|(_, b)| b) { -+ Some(b'\\') => match bytes.next().map(|(_, b)| b) { -+ Some(b'x') => backslash_x_byte(&mut bytes), -+ Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'') -+ | Some(b'"') => true, -+ _ => false, -+ }, -+ b => b.is_some(), -+ }; -+ if !ok { -+ return Err(LexError); -+ } -+ let (offset, _) = bytes.next().ok_or(LexError)?; -+ if !input.chars().as_str().is_char_boundary(offset) { -+ return Err(LexError); -+ } -+ let input = input.advance(offset).parse("'")?; -+ Ok(literal_suffix(input)) -+} -+ -+fn character(input: Cursor) -> Result { -+ let input = input.parse("'")?; -+ let mut chars = input.char_indices(); -+ let ok = match chars.next().map(|(_, ch)| ch) { -+ Some('\\') => match chars.next().map(|(_, ch)| ch) { -+ Some('x') => backslash_x_char(&mut chars), -+ Some('u') => backslash_u(&mut chars), -+ Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => { -+ true -+ } -+ _ => false, -+ }, -+ ch => ch.is_some(), -+ }; -+ if !ok { -+ return Err(LexError); -+ } -+ let (idx, _) = chars.next().ok_or(LexError)?; -+ let input = input.advance(idx).parse("'")?; -+ Ok(literal_suffix(input)) -+} -+ -+macro_rules! next_ch { -+ ($chars:ident @ $pat:pat $(| $rest:pat)*) => { -+ match $chars.next() { -+ Some((_, ch)) => match ch { -+ $pat $(| $rest)* => ch, -+ _ => return false, -+ }, -+ None => return false, -+ } -+ }; -+} -+ -+fn backslash_x_char(chars: &mut I) -> bool -+where -+ I: Iterator, -+{ -+ next_ch!(chars @ '0'..='7'); -+ next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); -+ true -+} -+ -+fn backslash_x_byte(chars: &mut I) -> bool -+where -+ I: Iterator, -+{ -+ next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); -+ next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); -+ true -+} -+ -+fn backslash_u(chars: &mut I) -> bool -+where -+ I: Iterator, -+{ -+ next_ch!(chars @ '{'); -+ next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); -+ loop { -+ let c = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F' | '_' | '}'); -+ if c == '}' { -+ return true; -+ } -+ } -+} -+ -+fn float(input: Cursor) -> Result { -+ let mut rest = float_digits(input)?; -+ if let Some(ch) = rest.chars().next() { -+ if is_ident_start(ch) { -+ rest = ident_not_raw(rest)?.0; -+ } -+ } -+ word_break(rest) -+} -+ -+fn float_digits(input: Cursor) -> Result { -+ let mut chars = input.chars().peekable(); -+ match chars.next() { -+ Some(ch) if ch >= '0' && ch <= '9' => {} -+ _ => return Err(LexError), -+ } -+ -+ let mut len = 1; -+ let mut has_dot = false; -+ let mut has_exp = false; -+ while let Some(&ch) = chars.peek() { -+ match ch { -+ '0'..='9' | '_' => { -+ chars.next(); -+ len += 1; -+ } -+ '.' => { -+ if has_dot { -+ break; -+ } -+ chars.next(); -+ if chars -+ .peek() -+ .map(|&ch| ch == '.' || is_ident_start(ch)) -+ .unwrap_or(false) -+ { -+ return Err(LexError); -+ } -+ len += 1; -+ has_dot = true; -+ } -+ 'e' | 'E' => { -+ chars.next(); -+ len += 1; -+ has_exp = true; -+ break; -+ } -+ _ => break, -+ } -+ } -+ -+ let rest = input.advance(len); -+ if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) { -+ return Err(LexError); -+ } -+ -+ if has_exp { -+ let mut has_exp_value = false; -+ while let Some(&ch) = chars.peek() { -+ match ch { -+ '+' | '-' => { -+ if has_exp_value { -+ break; -+ } -+ chars.next(); -+ len += 1; -+ } -+ '0'..='9' => { -+ chars.next(); -+ len += 1; -+ has_exp_value = true; -+ } -+ '_' => { -+ chars.next(); -+ len += 1; -+ } -+ _ => break, -+ } -+ } -+ if !has_exp_value { -+ return Err(LexError); -+ } -+ } -+ -+ Ok(input.advance(len)) -+} -+ -+fn int(input: Cursor) -> Result { -+ let mut rest = digits(input)?; -+ if let Some(ch) = rest.chars().next() { -+ if is_ident_start(ch) { -+ rest = ident_not_raw(rest)?.0; -+ } -+ } -+ word_break(rest) -+} -+ -+fn digits(mut input: Cursor) -> Result { -+ let base = if input.starts_with("0x") { -+ input = input.advance(2); -+ 16 -+ } else if input.starts_with("0o") { -+ input = input.advance(2); -+ 8 -+ } else if input.starts_with("0b") { -+ input = input.advance(2); -+ 2 -+ } else { -+ 10 -+ }; -+ -+ let mut len = 0; -+ let mut empty = true; -+ for b in input.bytes() { -+ let digit = match b { -+ b'0'..=b'9' => (b - b'0') as u64, -+ b'a'..=b'f' => 10 + (b - b'a') as u64, -+ b'A'..=b'F' => 10 + (b - b'A') as u64, -+ b'_' => { -+ if empty && base == 10 { -+ return Err(LexError); -+ } -+ len += 1; -+ continue; -+ } -+ _ => break, -+ }; -+ if digit >= base { -+ return Err(LexError); -+ } -+ len += 1; -+ empty = false; -+ } -+ if empty { -+ Err(LexError) -+ } else { -+ Ok(input.advance(len)) -+ } -+} -+ -+fn op(input: Cursor) -> PResult { -+ match op_char(input) { -+ Ok((rest, '\'')) => { -+ ident(rest)?; -+ Ok((rest, Punct::new('\'', Spacing::Joint))) -+ } -+ Ok((rest, ch)) => { -+ let kind = match op_char(rest) { -+ Ok(_) => Spacing::Joint, -+ Err(LexError) => Spacing::Alone, -+ }; -+ Ok((rest, Punct::new(ch, kind))) -+ } -+ Err(LexError) => Err(LexError), -+ } -+} -+ -+fn op_char(input: Cursor) -> PResult { -+ if input.starts_with("//") || input.starts_with("/*") { -+ // Do not accept `/` of a comment as an op. -+ return Err(LexError); -+ } -+ -+ let mut chars = input.chars(); -+ let first = match chars.next() { -+ Some(ch) => ch, -+ None => { -+ return Err(LexError); -+ } -+ }; -+ let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; -+ if recognized.contains(first) { -+ Ok((input.advance(first.len_utf8()), first)) -+ } else { -+ Err(LexError) -+ } -+} -+ -+fn doc_comment(input: Cursor) -> PResult> { -+ #[cfg(span_locations)] -+ let lo = input.off; -+ let (rest, (comment, inner)) = doc_comment_contents(input)?; -+ let span = crate::Span::_new_stable(Span { -+ #[cfg(span_locations)] -+ lo, -+ #[cfg(span_locations)] -+ hi: rest.off, -+ }); -+ -+ let mut scan_for_bare_cr = comment; -+ while let Some(cr) = scan_for_bare_cr.find('\r') { -+ let rest = &scan_for_bare_cr[cr + 1..]; -+ if !rest.starts_with('\n') { -+ return Err(LexError); -+ } -+ scan_for_bare_cr = rest; -+ } -+ -+ let mut trees = Vec::new(); -+ trees.push(TokenTree::Punct(Punct::new('#', Spacing::Alone))); -+ if inner { -+ trees.push(Punct::new('!', Spacing::Alone).into()); -+ } -+ let mut stream = vec![ -+ TokenTree::Ident(crate::Ident::new("doc", span)), -+ TokenTree::Punct(Punct::new('=', Spacing::Alone)), -+ TokenTree::Literal(crate::Literal::string(comment)), -+ ]; -+ for tt in stream.iter_mut() { -+ tt.set_span(span); -+ } -+ let group = Group::new(Delimiter::Bracket, stream.into_iter().collect()); -+ trees.push(crate::Group::_new_stable(group).into()); -+ for tt in trees.iter_mut() { -+ tt.set_span(span); -+ } -+ Ok((rest, trees)) -+} -+ -+fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> { -+ if input.starts_with("//!") { -+ let input = input.advance(3); -+ let (input, s) = take_until_newline_or_eof(input); -+ Ok((input, (s, true))) -+ } else if input.starts_with("/*!") { -+ let (input, s) = block_comment(input)?; -+ Ok((input, (&s[3..s.len() - 2], true))) -+ } else if input.starts_with("///") { -+ let input = input.advance(3); -+ if input.starts_with("/") { -+ return Err(LexError); -+ } -+ let (input, s) = take_until_newline_or_eof(input); -+ Ok((input, (s, false))) -+ } else if input.starts_with("/**") && !input.rest[3..].starts_with('*') { -+ let (input, s) = block_comment(input)?; -+ Ok((input, (&s[3..s.len() - 2], false))) -+ } else { -+ Err(LexError) -+ } -+} -+ -+fn take_until_newline_or_eof(input: Cursor) -> (Cursor, &str) { -+ let chars = input.char_indices(); -+ -+ for (i, ch) in chars { -+ if ch == '\n' { -+ return (input.advance(i), &input.rest[..i]); -+ } else if ch == '\r' && input.rest[i + 1..].starts_with('\n') { -+ return (input.advance(i + 1), &input.rest[..i]); -+ } -+ } -+ -+ (input.advance(input.len()), input.rest) -+} -diff --git a/third_party/rust/proc-macro2/src/strnom.rs b/third_party/rust/proc-macro2/src/strnom.rs -deleted file mode 100644 ---- a/third_party/rust/proc-macro2/src/strnom.rs -+++ /dev/null -@@ -1,391 +0,0 @@ --//! Adapted from [`nom`](https://github.com/Geal/nom). -- --use crate::fallback::LexError; --use std::str::{Bytes, CharIndices, Chars}; --use unicode_xid::UnicodeXID; -- --#[derive(Copy, Clone, Eq, PartialEq)] --pub struct Cursor<'a> { -- pub rest: &'a str, -- #[cfg(span_locations)] -- pub off: u32, --} -- --impl<'a> Cursor<'a> { -- #[cfg(not(span_locations))] -- pub fn advance(&self, amt: usize) -> Cursor<'a> { -- Cursor { -- rest: &self.rest[amt..], -- } -- } -- #[cfg(span_locations)] -- pub fn advance(&self, amt: usize) -> Cursor<'a> { -- Cursor { -- rest: &self.rest[amt..], -- off: self.off + (amt as u32), -- } -- } -- -- pub fn find(&self, p: char) -> Option { -- self.rest.find(p) -- } -- -- pub fn starts_with(&self, s: &str) -> bool { -- self.rest.starts_with(s) -- } -- -- pub fn is_empty(&self) -> bool { -- self.rest.is_empty() -- } -- -- pub fn len(&self) -> usize { -- self.rest.len() -- } -- -- pub fn as_bytes(&self) -> &'a [u8] { -- self.rest.as_bytes() -- } -- -- pub fn bytes(&self) -> Bytes<'a> { -- self.rest.bytes() -- } -- -- pub fn chars(&self) -> Chars<'a> { -- self.rest.chars() -- } -- -- pub fn char_indices(&self) -> CharIndices<'a> { -- self.rest.char_indices() -- } --} -- --pub type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>; -- --pub fn whitespace(input: Cursor) -> PResult<()> { -- if input.is_empty() { -- return Err(LexError); -- } -- -- let bytes = input.as_bytes(); -- let mut i = 0; -- while i < bytes.len() { -- let s = input.advance(i); -- if bytes[i] == b'/' { -- if s.starts_with("//") -- && (!s.starts_with("///") || s.starts_with("////")) -- && !s.starts_with("//!") -- { -- if let Some(len) = s.find('\n') { -- i += len + 1; -- continue; -- } -- break; -- } else if s.starts_with("/**/") { -- i += 4; -- continue; -- } else if s.starts_with("/*") -- && (!s.starts_with("/**") || s.starts_with("/***")) -- && !s.starts_with("/*!") -- { -- let (_, com) = block_comment(s)?; -- i += com.len(); -- continue; -- } -- } -- match bytes[i] { -- b' ' | 0x09..=0x0d => { -- i += 1; -- continue; -- } -- b if b <= 0x7f => {} -- _ => { -- let ch = s.chars().next().unwrap(); -- if is_whitespace(ch) { -- i += ch.len_utf8(); -- continue; -- } -- } -- } -- return if i > 0 { Ok((s, ())) } else { Err(LexError) }; -- } -- Ok((input.advance(input.len()), ())) --} -- --pub fn block_comment(input: Cursor) -> PResult<&str> { -- if !input.starts_with("/*") { -- return Err(LexError); -- } -- -- let mut depth = 0; -- let bytes = input.as_bytes(); -- let mut i = 0; -- let upper = bytes.len() - 1; -- while i < upper { -- if bytes[i] == b'/' && bytes[i + 1] == b'*' { -- depth += 1; -- i += 1; // eat '*' -- } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { -- depth -= 1; -- if depth == 0 { -- return Ok((input.advance(i + 2), &input.rest[..i + 2])); -- } -- i += 1; // eat '/' -- } -- i += 1; -- } -- Err(LexError) --} -- --pub fn skip_whitespace(input: Cursor) -> Cursor { -- match whitespace(input) { -- Ok((rest, _)) => rest, -- Err(LexError) => input, -- } --} -- --fn is_whitespace(ch: char) -> bool { -- // Rust treats left-to-right mark and right-to-left mark as whitespace -- ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' --} -- --pub fn word_break(input: Cursor) -> PResult<()> { -- match input.chars().next() { -- Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError), -- Some(_) | None => Ok((input, ())), -- } --} -- --macro_rules! named { -- ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => { -- fn $name<'a>(i: Cursor<'a>) -> $crate::strnom::PResult<'a, $o> { -- $submac!(i, $($args)*) -- } -- }; --} -- --macro_rules! alt { -- ($i:expr, $e:ident | $($rest:tt)*) => { -- alt!($i, call!($e) | $($rest)*) -- }; -- -- ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => { -- match $subrule!($i, $($args)*) { -- res @ Ok(_) => res, -- _ => alt!($i, $($rest)*) -- } -- }; -- -- ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => { -- match $subrule!($i, $($args)*) { -- Ok((i, o)) => Ok((i, $gen(o))), -- Err(LexError) => alt!($i, $($rest)*) -- } -- }; -- -- ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => { -- alt!($i, call!($e) => { $gen } | $($rest)*) -- }; -- -- ($i:expr, $e:ident => { $gen:expr }) => { -- alt!($i, call!($e) => { $gen }) -- }; -- -- ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => { -- match $subrule!($i, $($args)*) { -- Ok((i, o)) => Ok((i, $gen(o))), -- Err(LexError) => Err(LexError), -- } -- }; -- -- ($i:expr, $e:ident) => { -- alt!($i, call!($e)) -- }; -- -- ($i:expr, $subrule:ident!( $($args:tt)*)) => { -- $subrule!($i, $($args)*) -- }; --} -- --macro_rules! do_parse { -- ($i:expr, ( $($rest:expr),* )) => { -- Ok(($i, ( $($rest),* ))) -- }; -- -- ($i:expr, $e:ident >> $($rest:tt)*) => { -- do_parse!($i, call!($e) >> $($rest)*) -- }; -- -- ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => { -- match $submac!($i, $($args)*) { -- Err(LexError) => Err(LexError), -- Ok((i, _)) => do_parse!(i, $($rest)*), -- } -- }; -- -- ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => { -- do_parse!($i, $field: call!($e) >> $($rest)*) -- }; -- -- ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => { -- match $submac!($i, $($args)*) { -- Err(LexError) => Err(LexError), -- Ok((i, o)) => { -- let $field = o; -- do_parse!(i, $($rest)*) -- }, -- } -- }; --} -- --macro_rules! peek { -- ($i:expr, $submac:ident!( $($args:tt)* )) => { -- match $submac!($i, $($args)*) { -- Ok((_, o)) => Ok(($i, o)), -- Err(LexError) => Err(LexError), -- } -- }; --} -- --macro_rules! call { -- ($i:expr, $fun:expr $(, $args:expr)*) => { -- $fun($i $(, $args)*) -- }; --} -- --macro_rules! option { -- ($i:expr, $f:expr) => { -- match $f($i) { -- Ok((i, o)) => Ok((i, Some(o))), -- Err(LexError) => Ok(($i, None)), -- } -- }; --} -- --macro_rules! take_until_newline_or_eof { -- ($i:expr,) => {{ -- if $i.len() == 0 { -- Ok(($i, "")) -- } else { -- match $i.find('\n') { -- Some(i) => Ok(($i.advance(i), &$i.rest[..i])), -- None => Ok(($i.advance($i.len()), &$i.rest[..$i.len()])), -- } -- } -- }}; --} -- --macro_rules! tuple { -- ($i:expr, $($rest:tt)*) => { -- tuple_parser!($i, (), $($rest)*) -- }; --} -- --/// Do not use directly. Use `tuple!`. --macro_rules! tuple_parser { -- ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => { -- tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*) -- }; -- -- ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => { -- match $submac!($i, $($args)*) { -- Err(LexError) => Err(LexError), -- Ok((i, o)) => tuple_parser!(i, (o), $($rest)*), -- } -- }; -- -- ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => { -- match $submac!($i, $($args)*) { -- Err(LexError) => Err(LexError), -- Ok((i, o)) => tuple_parser!(i, ($($parsed)* , o), $($rest)*), -- } -- }; -- -- ($i:expr, ($($parsed:tt),*), $e:ident) => { -- tuple_parser!($i, ($($parsed),*), call!($e)) -- }; -- -- ($i:expr, (), $submac:ident!( $($args:tt)* )) => { -- $submac!($i, $($args)*) -- }; -- -- ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => { -- match $submac!($i, $($args)*) { -- Err(LexError) => Err(LexError), -- Ok((i, o)) => Ok((i, ($($parsed),*, o))) -- } -- }; -- -- ($i:expr, ($($parsed:expr),*)) => { -- Ok(($i, ($($parsed),*))) -- }; --} -- --macro_rules! not { -- ($i:expr, $submac:ident!( $($args:tt)* )) => { -- match $submac!($i, $($args)*) { -- Ok((_, _)) => Err(LexError), -- Err(LexError) => Ok(($i, ())), -- } -- }; --} -- --macro_rules! tag { -- ($i:expr, $tag:expr) => { -- if $i.starts_with($tag) { -- Ok(($i.advance($tag.len()), &$i.rest[..$tag.len()])) -- } else { -- Err(LexError) -- } -- }; --} -- --macro_rules! punct { -- ($i:expr, $punct:expr) => { -- $crate::strnom::punct($i, $punct) -- }; --} -- --/// Do not use directly. Use `punct!`. --pub fn punct<'a>(input: Cursor<'a>, token: &'static str) -> PResult<'a, &'a str> { -- let input = skip_whitespace(input); -- if input.starts_with(token) { -- Ok((input.advance(token.len()), token)) -- } else { -- Err(LexError) -- } --} -- --macro_rules! preceded { -- ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => { -- match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) { -- Ok((remaining, (_, o))) => Ok((remaining, o)), -- Err(LexError) => Err(LexError), -- } -- }; -- -- ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => { -- preceded!($i, $submac!($($args)*), call!($g)) -- }; --} -- --macro_rules! delimited { -- ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => { -- match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) { -- Err(LexError) => Err(LexError), -- Ok((i1, (_, o, _))) => Ok((i1, o)) -- } -- }; --} -- --macro_rules! map { -- ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => { -- match $submac!($i, $($args)*) { -- Err(LexError) => Err(LexError), -- Ok((i, o)) => Ok((i, call!(o, $g))) -- } -- }; -- -- ($i:expr, $f:expr, $g:expr) => { -- map!($i, call!($f), $g) -- }; --} -diff --git a/third_party/rust/proc-macro2/src/wrapper.rs b/third_party/rust/proc-macro2/src/wrapper.rs ---- a/third_party/rust/proc-macro2/src/wrapper.rs -+++ b/third_party/rust/proc-macro2/src/wrapper.rs -@@ -1,96 +1,39 @@ --use std::fmt; --use std::iter; -+use crate::detection::inside_proc_macro; -+use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; -+use std::fmt::{self, Debug, Display}; -+use std::iter::FromIterator; - use std::ops::RangeBounds; --use std::panic::{self, PanicInfo}; -+use std::panic; - #[cfg(super_unstable)] - use std::path::PathBuf; - use std::str::FromStr; - --use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; -- - #[derive(Clone)] --pub enum TokenStream { -+pub(crate) enum TokenStream { - Compiler(DeferredTokenStream), - Fallback(fallback::TokenStream), - } - - // Work around https://github.com/rust-lang/rust/issues/65080. - // In `impl Extend for TokenStream` which is used heavily by quote, - // we hold on to the appended tokens and do proc_macro::TokenStream::extend as - // late as possible to batch together consecutive uses of the Extend impl. - #[derive(Clone)] --pub struct DeferredTokenStream { -+pub(crate) struct DeferredTokenStream { - stream: proc_macro::TokenStream, - extra: Vec, - } - --pub enum LexError { -+pub(crate) enum LexError { - Compiler(proc_macro::LexError), - Fallback(fallback::LexError), - } - --fn nightly_works() -> bool { -- use std::sync::atomic::*; -- use std::sync::Once; -- -- static WORKS: AtomicUsize = AtomicUsize::new(0); -- static INIT: Once = Once::new(); -- -- match WORKS.load(Ordering::SeqCst) { -- 1 => return false, -- 2 => return true, -- _ => {} -- } -- -- // Swap in a null panic hook to avoid printing "thread panicked" to stderr, -- // then use catch_unwind to determine whether the compiler's proc_macro is -- // working. When proc-macro2 is used from outside of a procedural macro all -- // of the proc_macro crate's APIs currently panic. -- // -- // The Once is to prevent the possibility of this ordering: -- // -- // thread 1 calls take_hook, gets the user's original hook -- // thread 1 calls set_hook with the null hook -- // thread 2 calls take_hook, thinks null hook is the original hook -- // thread 2 calls set_hook with the null hook -- // thread 1 calls set_hook with the actual original hook -- // thread 2 calls set_hook with what it thinks is the original hook -- // -- // in which the user's hook has been lost. -- // -- // There is still a race condition where a panic in a different thread can -- // happen during the interval that the user's original panic hook is -- // unregistered such that their hook is incorrectly not called. This is -- // sufficiently unlikely and less bad than printing panic messages to stderr -- // on correct use of this crate. Maybe there is a libstd feature request -- // here. For now, if a user needs to guarantee that this failure mode does -- // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from -- // the main thread before launching any other threads. -- INIT.call_once(|| { -- type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; -- -- let null_hook: Box = Box::new(|_panic_info| { /* ignore */ }); -- let sanity_check = &*null_hook as *const PanicHook; -- let original_hook = panic::take_hook(); -- panic::set_hook(null_hook); -- -- let works = panic::catch_unwind(|| proc_macro::Span::call_site()).is_ok(); -- WORKS.store(works as usize + 1, Ordering::SeqCst); -- -- let hopefully_null_hook = panic::take_hook(); -- panic::set_hook(original_hook); -- if sanity_check != &*hopefully_null_hook { -- panic!("observed race condition in proc_macro2::nightly_works"); -- } -- }); -- nightly_works() --} -- - fn mismatch() -> ! { - panic!("stable/nightly mismatch") - } - - impl DeferredTokenStream { - fn new(stream: proc_macro::TokenStream) -> Self { - DeferredTokenStream { - stream, -@@ -98,28 +41,33 @@ impl DeferredTokenStream { - } - } - - fn is_empty(&self) -> bool { - self.stream.is_empty() && self.extra.is_empty() - } - - fn evaluate_now(&mut self) { -- self.stream.extend(self.extra.drain(..)); -+ // If-check provides a fast short circuit for the common case of `extra` -+ // being empty, which saves a round trip over the proc macro bridge. -+ // Improves macro expansion time in winrt by 6% in debug mode. -+ if !self.extra.is_empty() { -+ self.stream.extend(self.extra.drain(..)); -+ } - } - - fn into_token_stream(mut self) -> proc_macro::TokenStream { - self.evaluate_now(); - self.stream - } - } - - impl TokenStream { - pub fn new() -> TokenStream { -- if nightly_works() { -+ if inside_proc_macro() { - TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) - } else { - TokenStream::Fallback(fallback::TokenStream::new()) - } - } - - pub fn is_empty(&self) -> bool { - match self { -@@ -142,31 +90,37 @@ impl TokenStream { - } - } - } - - impl FromStr for TokenStream { - type Err = LexError; - - fn from_str(src: &str) -> Result { -- if nightly_works() { -+ if inside_proc_macro() { - Ok(TokenStream::Compiler(DeferredTokenStream::new( -- src.parse()?, -+ proc_macro_parse(src)?, - ))) - } else { - Ok(TokenStream::Fallback(src.parse()?)) - } - } - } - --impl fmt::Display for TokenStream { -+// Work around https://github.com/rust-lang/rust/issues/58736. -+fn proc_macro_parse(src: &str) -> Result { -+ panic::catch_unwind(|| src.parse().map_err(LexError::Compiler)) -+ .unwrap_or(Err(LexError::Fallback(fallback::LexError))) -+} -+ -+impl Display for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- TokenStream::Compiler(tts) => tts.clone().into_token_stream().fmt(f), -- TokenStream::Fallback(tts) => tts.fmt(f), -+ TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f), -+ TokenStream::Fallback(tts) => Display::fmt(tts, f), - } - } - } - - impl From for TokenStream { - fn from(inner: proc_macro::TokenStream) -> TokenStream { - TokenStream::Compiler(DeferredTokenStream::new(inner)) - } -@@ -182,17 +136,17 @@ impl From for proc_macro::T - } - - impl From for TokenStream { - fn from(inner: fallback::TokenStream) -> TokenStream { - TokenStream::Fallback(inner) - } - } - --// Assumes nightly_works(). -+// Assumes inside_proc_macro(). - fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { - match token { - TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(), - TokenTree::Punct(tt) => { - let spacing = match tt.spacing() { - Spacing::Joint => proc_macro::Spacing::Joint, - Spacing::Alone => proc_macro::Spacing::Alone, - }; -@@ -202,37 +156,37 @@ fn into_compiler_token(token: TokenTree) - } - TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(), - TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(), - } - } - - impl From for TokenStream { - fn from(token: TokenTree) -> TokenStream { -- if nightly_works() { -+ if inside_proc_macro() { - TokenStream::Compiler(DeferredTokenStream::new(into_compiler_token(token).into())) - } else { - TokenStream::Fallback(token.into()) - } - } - } - --impl iter::FromIterator for TokenStream { -+impl FromIterator for TokenStream { - fn from_iter>(trees: I) -> Self { -- if nightly_works() { -+ if inside_proc_macro() { - TokenStream::Compiler(DeferredTokenStream::new( - trees.into_iter().map(into_compiler_token).collect(), - )) - } else { - TokenStream::Fallback(trees.into_iter().collect()) - } - } - } - --impl iter::FromIterator for TokenStream { -+impl FromIterator for TokenStream { - fn from_iter>(streams: I) -> Self { - let mut streams = streams.into_iter(); - match streams.next() { - Some(TokenStream::Compiler(mut first)) => { - first.evaluate_now(); - first.stream.extend(streams.map(|s| match s { - TokenStream::Compiler(s) => s.into_token_stream(), - TokenStream::Fallback(_) => mismatch(), -@@ -247,75 +201,76 @@ impl iter::FromIterator for - TokenStream::Fallback(first) - } - None => TokenStream::new(), - } - } - } - - impl Extend for TokenStream { -- fn extend>(&mut self, streams: I) { -+ fn extend>(&mut self, stream: I) { - match self { - TokenStream::Compiler(tts) => { - // Here is the reason for DeferredTokenStream. -- tts.extra -- .extend(streams.into_iter().map(into_compiler_token)); -+ for token in stream { -+ tts.extra.push(into_compiler_token(token)); -+ } - } -- TokenStream::Fallback(tts) => tts.extend(streams), -+ TokenStream::Fallback(tts) => tts.extend(stream), - } - } - } - - impl Extend for TokenStream { - fn extend>(&mut self, streams: I) { - match self { - TokenStream::Compiler(tts) => { - tts.evaluate_now(); - tts.stream -- .extend(streams.into_iter().map(|stream| stream.unwrap_nightly())); -+ .extend(streams.into_iter().map(TokenStream::unwrap_nightly)); - } - TokenStream::Fallback(tts) => { -- tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable())); -+ tts.extend(streams.into_iter().map(TokenStream::unwrap_stable)); - } - } - } - } - --impl fmt::Debug for TokenStream { -+impl Debug for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- TokenStream::Compiler(tts) => tts.clone().into_token_stream().fmt(f), -- TokenStream::Fallback(tts) => tts.fmt(f), -+ TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f), -+ TokenStream::Fallback(tts) => Debug::fmt(tts, f), - } - } - } - - impl From for LexError { - fn from(e: proc_macro::LexError) -> LexError { - LexError::Compiler(e) - } - } - - impl From for LexError { - fn from(e: fallback::LexError) -> LexError { - LexError::Fallback(e) - } - } - --impl fmt::Debug for LexError { -+impl Debug for LexError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- LexError::Compiler(e) => e.fmt(f), -- LexError::Fallback(e) => e.fmt(f), -+ LexError::Compiler(e) => Debug::fmt(e, f), -+ LexError::Fallback(e) => Debug::fmt(e, f), - } - } - } - - #[derive(Clone)] --pub enum TokenTreeIter { -+pub(crate) enum TokenTreeIter { - Compiler(proc_macro::token_stream::IntoIter), - Fallback(fallback::TokenTreeIter), - } - - impl IntoIterator for TokenStream { - type Item = TokenTree; - type IntoIter = TokenTreeIter; - -@@ -356,25 +311,25 @@ impl Iterator for TokenTreeIter { - fn size_hint(&self) -> (usize, Option) { - match self { - TokenTreeIter::Compiler(tts) => tts.size_hint(), - TokenTreeIter::Fallback(tts) => tts.size_hint(), - } - } - } - --impl fmt::Debug for TokenTreeIter { -+impl Debug for TokenTreeIter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("TokenTreeIter").finish() - } - } - - #[derive(Clone, PartialEq, Eq)] - #[cfg(super_unstable)] --pub enum SourceFile { -+pub(crate) enum SourceFile { - Compiler(proc_macro::SourceFile), - Fallback(fallback::SourceFile), - } - - #[cfg(super_unstable)] - impl SourceFile { - fn nightly(sf: proc_macro::SourceFile) -> Self { - SourceFile::Compiler(sf) -@@ -392,68 +347,87 @@ impl SourceFile { - match self { - SourceFile::Compiler(a) => a.is_real(), - SourceFile::Fallback(a) => a.is_real(), - } - } - } - - #[cfg(super_unstable)] --impl fmt::Debug for SourceFile { -+impl Debug for SourceFile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- SourceFile::Compiler(a) => a.fmt(f), -- SourceFile::Fallback(a) => a.fmt(f), -+ SourceFile::Compiler(a) => Debug::fmt(a, f), -+ SourceFile::Fallback(a) => Debug::fmt(a, f), - } - } - } - - #[cfg(any(super_unstable, feature = "span-locations"))] --pub struct LineColumn { -+pub(crate) struct LineColumn { - pub line: usize, - pub column: usize, - } - - #[derive(Copy, Clone)] --pub enum Span { -+pub(crate) enum Span { - Compiler(proc_macro::Span), - Fallback(fallback::Span), - } - - impl Span { - pub fn call_site() -> Span { -- if nightly_works() { -+ if inside_proc_macro() { - Span::Compiler(proc_macro::Span::call_site()) - } else { - Span::Fallback(fallback::Span::call_site()) - } - } - -+ #[cfg(hygiene)] -+ pub fn mixed_site() -> Span { -+ if inside_proc_macro() { -+ Span::Compiler(proc_macro::Span::mixed_site()) -+ } else { -+ Span::Fallback(fallback::Span::mixed_site()) -+ } -+ } -+ - #[cfg(super_unstable)] - pub fn def_site() -> Span { -- if nightly_works() { -+ if inside_proc_macro() { - Span::Compiler(proc_macro::Span::def_site()) - } else { - Span::Fallback(fallback::Span::def_site()) - } - } - -- #[cfg(super_unstable)] - pub fn resolved_at(&self, other: Span) -> Span { - match (self, other) { -+ #[cfg(hygiene)] - (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), -+ -+ // Name resolution affects semantics, but location is only cosmetic -+ #[cfg(not(hygiene))] -+ (Span::Compiler(_), Span::Compiler(_)) => other, -+ - (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), - _ => mismatch(), - } - } - -- #[cfg(super_unstable)] - pub fn located_at(&self, other: Span) -> Span { - match (self, other) { -+ #[cfg(hygiene)] - (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), -+ -+ // Name resolution affects semantics, but location is only cosmetic -+ #[cfg(not(hygiene))] -+ (Span::Compiler(_), Span::Compiler(_)) => *self, -+ - (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), - _ => mismatch(), - } - } - - pub fn unwrap(self) -> proc_macro::Span { - match self { - Span::Compiler(s) => s, -@@ -537,36 +511,36 @@ impl From for crate::S - } - - impl From for Span { - fn from(inner: fallback::Span) -> Span { - Span::Fallback(inner) - } - } - --impl fmt::Debug for Span { -+impl Debug for Span { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- Span::Compiler(s) => s.fmt(f), -- Span::Fallback(s) => s.fmt(f), -+ Span::Compiler(s) => Debug::fmt(s, f), -+ Span::Fallback(s) => Debug::fmt(s, f), - } - } - } - --pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { -+pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { - match span { - Span::Compiler(s) => { - debug.field("span", &s); - } - Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s), - } - } - - #[derive(Clone)] --pub enum Group { -+pub(crate) enum Group { - Compiler(proc_macro::Group), - Fallback(fallback::Group), - } - - impl Group { - pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { - match stream { - TokenStream::Compiler(tts) => { -@@ -647,36 +621,36 @@ impl Group { - } - - impl From for Group { - fn from(g: fallback::Group) -> Self { - Group::Fallback(g) - } - } - --impl fmt::Display for Group { -+impl Display for Group { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self { -- Group::Compiler(group) => group.fmt(formatter), -- Group::Fallback(group) => group.fmt(formatter), -+ Group::Compiler(group) => Display::fmt(group, formatter), -+ Group::Fallback(group) => Display::fmt(group, formatter), - } - } - } - --impl fmt::Debug for Group { -+impl Debug for Group { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self { -- Group::Compiler(group) => group.fmt(formatter), -- Group::Fallback(group) => group.fmt(formatter), -+ Group::Compiler(group) => Debug::fmt(group, formatter), -+ Group::Fallback(group) => Debug::fmt(group, formatter), - } - } - } - - #[derive(Clone)] --pub enum Ident { -+pub(crate) enum Ident { - Compiler(proc_macro::Ident), - Fallback(fallback::Ident), - } - - impl Ident { - pub fn new(string: &str, span: Span) -> Ident { - match span { - Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)), -@@ -742,56 +716,56 @@ where - let other = other.as_ref(); - match self { - Ident::Compiler(t) => t.to_string() == other, - Ident::Fallback(t) => t == other, - } - } - } - --impl fmt::Display for Ident { -+impl Display for Ident { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- Ident::Compiler(t) => t.fmt(f), -- Ident::Fallback(t) => t.fmt(f), -+ Ident::Compiler(t) => Display::fmt(t, f), -+ Ident::Fallback(t) => Display::fmt(t, f), - } - } - } - --impl fmt::Debug for Ident { -+impl Debug for Ident { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- Ident::Compiler(t) => t.fmt(f), -- Ident::Fallback(t) => t.fmt(f), -+ Ident::Compiler(t) => Debug::fmt(t, f), -+ Ident::Fallback(t) => Debug::fmt(t, f), - } - } - } - - #[derive(Clone)] --pub enum Literal { -+pub(crate) enum Literal { - Compiler(proc_macro::Literal), - Fallback(fallback::Literal), - } - - macro_rules! suffixed_numbers { - ($($name:ident => $kind:ident,)*) => ($( - pub fn $name(n: $kind) -> Literal { -- if nightly_works() { -+ if inside_proc_macro() { - Literal::Compiler(proc_macro::Literal::$name(n)) - } else { - Literal::Fallback(fallback::Literal::$name(n)) - } - } - )*) - } - - macro_rules! unsuffixed_integers { - ($($name:ident => $kind:ident,)*) => ($( - pub fn $name(n: $kind) -> Literal { -- if nightly_works() { -+ if inside_proc_macro() { - Literal::Compiler(proc_macro::Literal::$name(n)) - } else { - Literal::Fallback(fallback::Literal::$name(n)) - } - } - )*) - } - -@@ -825,49 +799,49 @@ impl Literal { - i16_unsuffixed => i16, - i32_unsuffixed => i32, - i64_unsuffixed => i64, - i128_unsuffixed => i128, - isize_unsuffixed => isize, - } - - pub fn f32_unsuffixed(f: f32) -> Literal { -- if nightly_works() { -+ if inside_proc_macro() { - Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f)) - } else { - Literal::Fallback(fallback::Literal::f32_unsuffixed(f)) - } - } - - pub fn f64_unsuffixed(f: f64) -> Literal { -- if nightly_works() { -+ if inside_proc_macro() { - Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f)) - } else { - Literal::Fallback(fallback::Literal::f64_unsuffixed(f)) - } - } - - pub fn string(t: &str) -> Literal { -- if nightly_works() { -+ if inside_proc_macro() { - Literal::Compiler(proc_macro::Literal::string(t)) - } else { - Literal::Fallback(fallback::Literal::string(t)) - } - } - - pub fn character(t: char) -> Literal { -- if nightly_works() { -+ if inside_proc_macro() { - Literal::Compiler(proc_macro::Literal::character(t)) - } else { - Literal::Fallback(fallback::Literal::character(t)) - } - } - - pub fn byte_string(bytes: &[u8]) -> Literal { -- if nightly_works() { -+ if inside_proc_macro() { - Literal::Compiler(proc_macro::Literal::byte_string(bytes)) - } else { - Literal::Fallback(fallback::Literal::byte_string(bytes)) - } - } - - pub fn span(&self) -> Span { - match self { -@@ -903,25 +877,25 @@ impl Literal { - } - - impl From for Literal { - fn from(s: fallback::Literal) -> Literal { - Literal::Fallback(s) - } - } - --impl fmt::Display for Literal { -+impl Display for Literal { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- Literal::Compiler(t) => t.fmt(f), -- Literal::Fallback(t) => t.fmt(f), -+ Literal::Compiler(t) => Display::fmt(t, f), -+ Literal::Fallback(t) => Display::fmt(t, f), - } - } - } - --impl fmt::Debug for Literal { -+impl Debug for Literal { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { -- Literal::Compiler(t) => t.fmt(f), -- Literal::Fallback(t) => t.fmt(f), -+ Literal::Compiler(t) => Debug::fmt(t, f), -+ Literal::Fallback(t) => Debug::fmt(t, f), - } - } - } -diff --git a/third_party/rust/proc-macro2/tests/comments.rs b/third_party/rust/proc-macro2/tests/comments.rs -new file mode 100644 ---- /dev/null -+++ b/third_party/rust/proc-macro2/tests/comments.rs -@@ -0,0 +1,103 @@ -+use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree}; -+ -+// #[doc = "..."] -> "..." -+fn lit_of_outer_doc_comment(tokens: TokenStream) -> Literal { -+ lit_of_doc_comment(tokens, false) -+} -+ -+// #![doc = "..."] -> "..." -+fn lit_of_inner_doc_comment(tokens: TokenStream) -> Literal { -+ lit_of_doc_comment(tokens, true) -+} -+ -+fn lit_of_doc_comment(tokens: TokenStream, inner: bool) -> Literal { -+ let mut iter = tokens.clone().into_iter(); -+ match iter.next().unwrap() { -+ TokenTree::Punct(punct) => { -+ assert_eq!(punct.as_char(), '#'); -+ assert_eq!(punct.spacing(), Spacing::Alone); -+ } -+ _ => panic!("wrong token {:?}", tokens), -+ } -+ if inner { -+ match iter.next().unwrap() { -+ TokenTree::Punct(punct) => { -+ assert_eq!(punct.as_char(), '!'); -+ assert_eq!(punct.spacing(), Spacing::Alone); -+ } -+ _ => panic!("wrong token {:?}", tokens), -+ } -+ } -+ iter = match iter.next().unwrap() { -+ TokenTree::Group(group) => { -+ assert_eq!(group.delimiter(), Delimiter::Bracket); -+ assert!(iter.next().is_none(), "unexpected token {:?}", tokens); -+ group.stream().into_iter() -+ } -+ _ => panic!("wrong token {:?}", tokens), -+ }; -+ match iter.next().unwrap() { -+ TokenTree::Ident(ident) => assert_eq!(ident.to_string(), "doc"), -+ _ => panic!("wrong token {:?}", tokens), -+ } -+ match iter.next().unwrap() { -+ TokenTree::Punct(punct) => { -+ assert_eq!(punct.as_char(), '='); -+ assert_eq!(punct.spacing(), Spacing::Alone); -+ } -+ _ => panic!("wrong token {:?}", tokens), -+ } -+ match iter.next().unwrap() { -+ TokenTree::Literal(literal) => { -+ assert!(iter.next().is_none(), "unexpected token {:?}", tokens); -+ literal -+ } -+ _ => panic!("wrong token {:?}", tokens), -+ } -+} -+ -+#[test] -+fn closed_immediately() { -+ let stream = "/**/".parse::().unwrap(); -+ let tokens = stream.into_iter().collect::>(); -+ assert!(tokens.is_empty(), "not empty -- {:?}", tokens); -+} -+ -+#[test] -+fn incomplete() { -+ assert!("/*/".parse::().is_err()); -+} -+ -+#[test] -+fn lit() { -+ let stream = "/// doc".parse::().unwrap(); -+ let lit = lit_of_outer_doc_comment(stream); -+ assert_eq!(lit.to_string(), "\" doc\""); -+ -+ let stream = "//! doc".parse::().unwrap(); -+ let lit = lit_of_inner_doc_comment(stream); -+ assert_eq!(lit.to_string(), "\" doc\""); -+ -+ let stream = "/** doc */".parse::().unwrap(); -+ let lit = lit_of_outer_doc_comment(stream); -+ assert_eq!(lit.to_string(), "\" doc \""); -+ -+ let stream = "/*! doc */".parse::().unwrap(); -+ let lit = lit_of_inner_doc_comment(stream); -+ assert_eq!(lit.to_string(), "\" doc \""); -+} -+ -+#[test] -+fn carriage_return() { -+ let stream = "///\r\n".parse::().unwrap(); -+ let lit = lit_of_outer_doc_comment(stream); -+ assert_eq!(lit.to_string(), "\"\""); -+ -+ let stream = "/**\r\n*/".parse::().unwrap(); -+ let lit = lit_of_outer_doc_comment(stream); -+ assert_eq!(lit.to_string(), "\"\\r\\n\""); -+ -+ "///\r".parse::().unwrap_err(); -+ "///\r \n".parse::().unwrap_err(); -+ "/**\r \n*/".parse::().unwrap_err(); -+} -diff --git a/third_party/rust/proc-macro2/tests/test.rs b/third_party/rust/proc-macro2/tests/test.rs ---- a/third_party/rust/proc-macro2/tests/test.rs -+++ b/third_party/rust/proc-macro2/tests/test.rs -@@ -1,12 +1,11 @@ -+use proc_macro2::{Ident, Literal, Spacing, Span, TokenStream, TokenTree}; - use std::str::{self, FromStr}; - --use proc_macro2::{Ident, Literal, Spacing, Span, TokenStream, TokenTree}; -- - #[test] - fn idents() { - assert_eq!( - Ident::new("String", Span::call_site()).to_string(), - "String" - ); - assert_eq!(Ident::new("fn", Span::call_site()).to_string(), "fn"); - assert_eq!(Ident::new("_", Span::call_site()).to_string(), "_"); -@@ -105,16 +104,43 @@ fn literal_suffix() { - assert_eq!(token_count("999u256"), 1); - assert_eq!(token_count("999r#u256"), 3); - assert_eq!(token_count("1."), 1); - assert_eq!(token_count("1.f32"), 3); - assert_eq!(token_count("1.0_0"), 1); - assert_eq!(token_count("1._0"), 3); - assert_eq!(token_count("1._m"), 3); - assert_eq!(token_count("\"\"s"), 1); -+ assert_eq!(token_count("r\"\"r"), 1); -+ assert_eq!(token_count("b\"\"b"), 1); -+ assert_eq!(token_count("br\"\"br"), 1); -+ assert_eq!(token_count("r#\"\"#r"), 1); -+ assert_eq!(token_count("'c'c"), 1); -+ assert_eq!(token_count("b'b'b"), 1); -+} -+ -+#[test] -+fn literal_iter_negative() { -+ let negative_literal = Literal::i32_suffixed(-3); -+ let tokens = TokenStream::from(TokenTree::Literal(negative_literal)); -+ let mut iter = tokens.into_iter(); -+ match iter.next().unwrap() { -+ TokenTree::Punct(punct) => { -+ assert_eq!(punct.as_char(), '-'); -+ assert_eq!(punct.spacing(), Spacing::Alone); -+ } -+ unexpected => panic!("unexpected token {:?}", unexpected), -+ } -+ match iter.next().unwrap() { -+ TokenTree::Literal(literal) => { -+ assert_eq!(literal.to_string(), "3i32"); -+ } -+ unexpected => panic!("unexpected token {:?}", unexpected), -+ } -+ assert!(iter.next().is_none()); - } - - #[test] - fn roundtrip() { - fn roundtrip(p: &str) { - println!("parse: {}", p); - let s = p.parse::().unwrap().to_string(); - println!("first: {}", s); -@@ -161,46 +187,16 @@ fn fail() { - fail("' static"); - fail("r#1"); - fail("r#_"); - } - - #[cfg(span_locations)] - #[test] - fn span_test() { -- use proc_macro2::TokenTree; -- -- fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) { -- let ts = p.parse::().unwrap(); -- check_spans_internal(ts, &mut lines); -- } -- -- fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) { -- for i in ts { -- if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() { -- *lines = rest; -- -- let start = i.span().start(); -- assert_eq!(start.line, sline, "sline did not match for {}", i); -- assert_eq!(start.column, scol, "scol did not match for {}", i); -- -- let end = i.span().end(); -- assert_eq!(end.line, eline, "eline did not match for {}", i); -- assert_eq!(end.column, ecol, "ecol did not match for {}", i); -- -- match i { -- TokenTree::Group(ref g) => { -- check_spans_internal(g.stream().clone(), lines); -- } -- _ => {} -- } -- } -- } -- } -- - check_spans( - "\ - /// This is a document comment - testing 123 - { - testing 234 - }", - &[ -@@ -269,59 +265,17 @@ fn span_join() { - joined1.unwrap().source_file(), - source1[0].span().source_file() - ); - } - - #[test] - fn no_panic() { - let s = str::from_utf8(b"b\'\xc2\x86 \x00\x00\x00^\"").unwrap(); -- assert!(s.parse::().is_err()); --} -- --#[test] --fn tricky_doc_comment() { -- let stream = "/**/".parse::().unwrap(); -- let tokens = stream.into_iter().collect::>(); -- assert!(tokens.is_empty(), "not empty -- {:?}", tokens); -- -- let stream = "/// doc".parse::().unwrap(); -- let tokens = stream.into_iter().collect::>(); -- assert!(tokens.len() == 2, "not length 2 -- {:?}", tokens); -- match tokens[0] { -- proc_macro2::TokenTree::Punct(ref tt) => assert_eq!(tt.as_char(), '#'), -- _ => panic!("wrong token {:?}", tokens[0]), -- } -- let mut tokens = match tokens[1] { -- proc_macro2::TokenTree::Group(ref tt) => { -- assert_eq!(tt.delimiter(), proc_macro2::Delimiter::Bracket); -- tt.stream().into_iter() -- } -- _ => panic!("wrong token {:?}", tokens[0]), -- }; -- -- match tokens.next().unwrap() { -- proc_macro2::TokenTree::Ident(ref tt) => assert_eq!(tt.to_string(), "doc"), -- t => panic!("wrong token {:?}", t), -- } -- match tokens.next().unwrap() { -- proc_macro2::TokenTree::Punct(ref tt) => assert_eq!(tt.as_char(), '='), -- t => panic!("wrong token {:?}", t), -- } -- match tokens.next().unwrap() { -- proc_macro2::TokenTree::Literal(ref tt) => { -- assert_eq!(tt.to_string(), "\" doc\""); -- } -- t => panic!("wrong token {:?}", t), -- } -- assert!(tokens.next().is_none()); -- -- let stream = "//! doc".parse::().unwrap(); -- let tokens = stream.into_iter().collect::>(); -- assert!(tokens.len() == 3, "not length 3 -- {:?}", tokens); -+ assert!(s.parse::().is_err()); - } - - #[test] - fn op_before_comment() { - let mut tts = TokenStream::from_str("~// comment").unwrap().into_iter(); - match tts.next().unwrap() { - TokenTree::Punct(tt) => { - assert_eq!(tt.as_char(), '~'); -@@ -340,30 +294,30 @@ fn raw_identifier() { - } - assert!(tts.next().is_none()); - } - - #[test] - fn test_debug_ident() { - let ident = Ident::new("proc_macro", Span::call_site()); - -- #[cfg(not(procmacro2_semver_exempt))] -+ #[cfg(not(span_locations))] - let expected = "Ident(proc_macro)"; - -- #[cfg(procmacro2_semver_exempt)] -- let expected = "Ident { sym: proc_macro, span: bytes(0..0) }"; -+ #[cfg(span_locations)] -+ let expected = "Ident { sym: proc_macro }"; - - assert_eq!(expected, format!("{:?}", ident)); - } - - #[test] - fn test_debug_tokenstream() { - let tts = TokenStream::from_str("[a + 1]").unwrap(); - -- #[cfg(not(procmacro2_semver_exempt))] -+ #[cfg(not(span_locations))] - let expected = "\ - TokenStream [ - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - sym: a, - }, -@@ -374,17 +328,17 @@ TokenStream [ - Literal { - lit: 1, - }, - ], - }, - ]\ - "; - -- #[cfg(not(procmacro2_semver_exempt))] -+ #[cfg(not(span_locations))] - let expected_before_trailing_commas = "\ - TokenStream [ - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - sym: a - }, -@@ -395,17 +349,17 @@ TokenStream [ - Literal { - lit: 1 - } - ] - } - ]\ - "; - -- #[cfg(procmacro2_semver_exempt)] -+ #[cfg(span_locations)] - let expected = "\ - TokenStream [ - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - sym: a, - span: bytes(2..3), -@@ -420,17 +374,17 @@ TokenStream [ - span: bytes(6..7), - }, - ], - span: bytes(1..8), - }, - ]\ - "; - -- #[cfg(procmacro2_semver_exempt)] -+ #[cfg(span_locations)] - let expected_before_trailing_commas = "\ - TokenStream [ - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - sym: a, - span: bytes(2..3) -@@ -459,8 +413,85 @@ TokenStream [ - } - - #[test] - fn default_tokenstream_is_empty() { - let default_token_stream: TokenStream = Default::default(); - - assert!(default_token_stream.is_empty()); - } -+ -+#[test] -+fn tuple_indexing() { -+ // This behavior may change depending on https://github.com/rust-lang/rust/pull/71322 -+ let mut tokens = "tuple.0.0".parse::().unwrap().into_iter(); -+ assert_eq!("tuple", tokens.next().unwrap().to_string()); -+ assert_eq!(".", tokens.next().unwrap().to_string()); -+ assert_eq!("0.0", tokens.next().unwrap().to_string()); -+ assert!(tokens.next().is_none()); -+} -+ -+#[cfg(span_locations)] -+#[test] -+fn non_ascii_tokens() { -+ check_spans("// abc", &[]); -+ check_spans("// ábc", &[]); -+ check_spans("// abc x", &[]); -+ check_spans("// ábc x", &[]); -+ check_spans("/* abc */ x", &[(1, 10, 1, 11)]); -+ check_spans("/* ábc */ x", &[(1, 10, 1, 11)]); -+ check_spans("/* ab\nc */ x", &[(2, 5, 2, 6)]); -+ check_spans("/* áb\nc */ x", &[(2, 5, 2, 6)]); -+ check_spans("/*** abc */ x", &[(1, 12, 1, 13)]); -+ check_spans("/*** ábc */ x", &[(1, 12, 1, 13)]); -+ check_spans(r#""abc""#, &[(1, 0, 1, 5)]); -+ check_spans(r#""ábc""#, &[(1, 0, 1, 5)]); -+ check_spans(r###"r#"abc"#"###, &[(1, 0, 1, 8)]); -+ check_spans(r###"r#"ábc"#"###, &[(1, 0, 1, 8)]); -+ check_spans("r#\"a\nc\"#", &[(1, 0, 2, 3)]); -+ check_spans("r#\"á\nc\"#", &[(1, 0, 2, 3)]); -+ check_spans("'a'", &[(1, 0, 1, 3)]); -+ check_spans("'á'", &[(1, 0, 1, 3)]); -+ check_spans("//! abc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); -+ check_spans("//! ábc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); -+ check_spans("//! abc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); -+ check_spans("//! ábc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); -+ check_spans("/*! abc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]); -+ check_spans("/*! ábc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]); -+ check_spans("/*! a\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]); -+ check_spans("/*! á\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]); -+ check_spans("abc", &[(1, 0, 1, 3)]); -+ check_spans("ábc", &[(1, 0, 1, 3)]); -+ check_spans("ábć", &[(1, 0, 1, 3)]); -+ check_spans("abc// foo", &[(1, 0, 1, 3)]); -+ check_spans("ábc// foo", &[(1, 0, 1, 3)]); -+ check_spans("ábć// foo", &[(1, 0, 1, 3)]); -+ check_spans("b\"a\\\n c\"", &[(1, 0, 2, 3)]); -+ check_spans("b\"a\\\n\u{00a0}c\"", &[(1, 0, 2, 3)]); -+} -+ -+#[cfg(span_locations)] -+fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) { -+ let ts = p.parse::().unwrap(); -+ check_spans_internal(ts, &mut lines); -+ assert!(lines.is_empty(), "leftover ranges: {:?}", lines); -+} -+ -+#[cfg(span_locations)] -+fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) { -+ for i in ts { -+ if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() { -+ *lines = rest; -+ -+ let start = i.span().start(); -+ assert_eq!(start.line, sline, "sline did not match for {}", i); -+ assert_eq!(start.column, scol, "scol did not match for {}", i); -+ -+ let end = i.span().end(); -+ assert_eq!(end.line, eline, "eline did not match for {}", i); -+ assert_eq!(end.column, ecol, "ecol did not match for {}", i); -+ -+ if let TokenTree::Group(g) = i { -+ check_spans_internal(g.stream().clone(), lines); -+ } -+ } -+ } -+} -diff --git a/third_party/rust/proc-macro2/tests/test_fmt.rs b/third_party/rust/proc-macro2/tests/test_fmt.rs -new file mode 100644 ---- /dev/null -+++ b/third_party/rust/proc-macro2/tests/test_fmt.rs -@@ -0,0 +1,26 @@ -+use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; -+use std::iter::{self, FromIterator}; -+ -+#[test] -+fn test_fmt_group() { -+ let ident = Ident::new("x", Span::call_site()); -+ let inner = TokenStream::from_iter(iter::once(TokenTree::Ident(ident))); -+ let parens_empty = Group::new(Delimiter::Parenthesis, TokenStream::new()); -+ let parens_nonempty = Group::new(Delimiter::Parenthesis, inner.clone()); -+ let brackets_empty = Group::new(Delimiter::Bracket, TokenStream::new()); -+ let brackets_nonempty = Group::new(Delimiter::Bracket, inner.clone()); -+ let braces_empty = Group::new(Delimiter::Brace, TokenStream::new()); -+ let braces_nonempty = Group::new(Delimiter::Brace, inner.clone()); -+ let none_empty = Group::new(Delimiter::None, TokenStream::new()); -+ let none_nonempty = Group::new(Delimiter::None, inner.clone()); -+ -+ // Matches libproc_macro. -+ assert_eq!("()", parens_empty.to_string()); -+ assert_eq!("(x)", parens_nonempty.to_string()); -+ assert_eq!("[]", brackets_empty.to_string()); -+ assert_eq!("[x]", brackets_nonempty.to_string()); -+ assert_eq!("{ }", braces_empty.to_string()); -+ assert_eq!("{ x }", braces_nonempty.to_string()); -+ assert_eq!("", none_empty.to_string()); -+ assert_eq!("x", none_nonempty.to_string()); -+} -diff --git a/third_party/rust/syn/.cargo-checksum.json b/third_party/rust/syn/.cargo-checksum.json ---- a/third_party/rust/syn/.cargo-checksum.json -+++ b/third_party/rust/syn/.cargo-checksum.json -@@ -1,1 +1,1 @@ --{"files":{"Cargo.toml":"484d29864d333a361652fa4e24e1dcfab9efa47705ffd8c106d802eb03b78da7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"ca605417b6db8c995458f8407afaad6c177aedcc2274004283600f5638fa1b0c","benches/file.rs":"b45211cc4a0296a77aac2b4de16dbc6b5cb66adfb5afac00a77bccea87f43968","benches/rust.rs":"9cc0f62e944f1583d05c43a395a1556731501cf5976ef67a081f4f6387f883ba","build.rs":"7423ab199728d55c7d64c44b7c6729cfd93bd8273366a77707353003e27565d7","src/attr.rs":"cf81add298f0e75c35a9980a59bc3c2fd3fe933635830d1591374eeb2487c225","src/await.rs":"18f0b2ecb319991f891e300011424985e3cf33d166ea9f29f22d575fc8c83a76","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"2a432c11a3da67a21d46c2272bf9ce60a0bb20893b5750027bbd8ca3e843ab35","src/custom_keyword.rs":"589e46ec1be9a04d6de12c0b8cadf87cc1c05606ed46ddea62e9869cbca4a191","src/custom_punctuation.rs":"2ba2e294e15a0fce7ede3686c42b2891797079a724dd1193b66e7d305624c891","src/data.rs":"cc9b250d084e444782d3ff5e63c1ba387cbde8f7f2e977eab9846d920b4b8c3f","src/derive.rs":"c18878f14be5d5ab11fd7dda2d2ff1ff75c9662daf11eed033de62e4d0670a89","src/discouraged.rs":"50e10915695c4d14f64a78e20ecbef90a2cd53a7c26ee3426a2524a8ee5c9cbf","src/error.rs":"2c17a402f83ed5ae4ad96e753216771bef620235c2ff1ccc23f4bbafc7266fe1","src/export.rs":"dcae67456278c0339acfbcbb4737b8d37cfba5a150ae789f31f4be79abf7e726","src/expr.rs":"871d8eeb43cef02ef88de3bea7477b79b4eabc096a0899dde0e5750edf482f49","src/ext.rs":"b97ed549490b9248b5b5df31b3d5b08ba8791e23e6c5d3a1157a0363eb683ff3","src/file.rs":"3cc2bf5c709238d515a557f721f231c8c725b196400de051f945b549299d38a7","src/gen/fold.rs":"10b3ae33d0ce410d6bbe8b93be9d5f9e856c7dc8212133cc46b703f97d548190","src/gen/visit.rs":"e0f5798552d186024696b7bfc7219d4ff53b0e45f735a83e77cbb6b6578c5fa4","src/gen/visit_mut.rs":"9f7dda83907969971dba84d545aaa563b0728e54db97ffab5050fdf43a79c731","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"d845d7a828863123a5187fd0fe59c9dae3636f63bad302bd035792eed3dcb1ba","src/group.rs":"119b62d8481b4b1c327639bed40e114bf1969765250b68186628247fd4144b3b","src/ident.rs":"503156ce51a7ef0420892e8dbf2ecf8fe51f42a84d52cc2c05654e1a83020cbf","src/item.rs":"213f2f58c65ee1aa222f111bc9b1be681f8fb069caed04ca56586839979318d0","src/keyword.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/lib.rs":"24778e9f15e8025e75aca114c712716ada586b471adb3b3b69278f4d39b8a21b","src/lifetime.rs":"905359708f772ec858954badde69ee016d29e6eeba1dd205b268445b1aff6f3a","src/lit.rs":"5bb0bddb94cbd256e50e92dc091a0baa09f1be40a77058b897507f3b17191e5d","src/lookahead.rs":"5cce8b4cb345a85c24a452ea6d78eadb76f01ca0a789cbf5ce35108334904173","src/mac.rs":"6b468244cc07e3f2f10419f833d9e2ed23edbcd6dc34cf21c5947633699db964","src/macros.rs":"0d8c3bab47539aa2d00bec64e92c901ea2c9c0af74c868051c0905b82650f970","src/op.rs":"93cd44770bb110deadf807a01d9a666efe644b6e3010f4b51cae77ee7438cfbb","src/parse.rs":"5017123c249ebc65866af113a0ad671814b9873f47568180e6539a305eb0317d","src/parse_macro_input.rs":"f799aadb7216c2d333b579f48ed2fedfe07b5e96f004b25b569649ffbaa958d2","src/parse_quote.rs":"81575bf60b18b0d8624d7025a5bcc8dcd6633ad70c454dee2a06e4c391700b6c","src/pat.rs":"db0f2263b9813de1f4e3e3e0396fe0080b1e11c8090c6b4fb6fca3cfbe22bc96","src/path.rs":"32e685ac7fd2d4b9989802de8f326a8d47fa710f86ec3e45fd9d3ff8fdfe97ef","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"384e7b317b26f24118eb4b0c39e949ee9f4f3e700a4c80e462342c83b2cc3282","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"adddb6acae14a0fa340df302b932c31e34b259706ce56fd82ab597ec424500e1","src/stmt.rs":"fbccf2b4da7980fe6ea8d99457d291577c0f225b370c1dd97da41abf2a18fcf7","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"761d8d1793560eb2b631c36ddfdbb14ac65178405f095453aa0e75e8816bdbb9","src/tt.rs":"1e32ae216d14d895ff621bf32bc611f138aa00108b0090be2cbaa0affebe8e2a","src/ty.rs":"ce052e0079b65b66bea4e9502d2ff2c90ad4b867904bf7eb892eb60aa3ef219a","tests/clone.sh":"961243d42540d9992090efbbd5478b7aa395671db64a6c28cdadb6edc610ebdf","tests/common/eq.rs":"a42d339808fd32dd4bfd440c254add8c56d5e2cde3a6bf0c88621b618ce5eaa7","tests/common/mod.rs":"20a3300016351fa210a193fbb0db059ef5125fa7909585ded64790004d4977ed","tests/common/parse.rs":"17ba6d1e74aaa3f8096c6d379d803221f12d95cca69927be047d6ddf8367647f","tests/debug/gen.rs":"57bd5cf585e0b86ad00f29f09ff3db3390c4a756d503514a9b28407500dcea3c","tests/debug/mod.rs":"462d6fe34ee75c3ca1207d4db2ff3bdee5b430b9f9ca632e5671d1588d3f76b3","tests/features/error.rs":"e0581a2869cbd237c2bc18a0a85272296e1577bb5f7317a67fa85e28e04eea6f","tests/features/mod.rs":"66a2605ec54ede29208da350f2bed536dfa763b58408d64d3fca3b13de64b64f","tests/macros/mod.rs":"3f2d758c0ba76b93f54b0c1fc22ad50edff8ef42629ba4d47ac7d7f823da8359","tests/repo/mod.rs":"e851a68972c9194a9a8d7b68538b16ed79ae81cba55e1a2ce210d1b759fb1a21","tests/test_asyncness.rs":"b6c46118b036e6807d24eb0e1779244b4fca23dac0d8031e9843b3edec484ce8","tests/test_attribute.rs":"2d8f18a98c989d3f7adaaeb1aeebd4f8413365ace63feecb37cb3f9db9db4d8f","tests/test_derive_input.rs":"477d80f914c54b526f8ff229788dc0e7798d118f6dcfa348f4c99755edb347b9","tests/test_expr.rs":"f35ca80566849a36e6ba6403d9663519eff37e4224360c468fedff8b561a643e","tests/test_generics.rs":"83a5dc07f5c5701c12625399262f7120b66f01a742523f3eda28da2cf2c87eb3","tests/test_grouping.rs":"aadd75215addd9e5a8fa2f9472117d4cb80f1e8b84e07f4c0845675c9014164f","tests/test_ident.rs":"236c239dd66f543f084f44ff747d7bc3962cf11a019a279777fe972f6e17aa4c","tests/test_iterators.rs":"718938da14778dcba06324d36a99d9317c9d45d81a34c6a44c47e1fa38085e9f","tests/test_lit.rs":"7dff2661a5ac586d6ed2fe27501cb8ff62f4cf3f6c91f596bff6057c67ad7857","tests/test_meta.rs":"8444dee084882243b107dfc8a6aac27f9382f9774162d1ac8ed8ec30d60c048e","tests/test_parse_buffer.rs":"b244bb4bc41ff06d21f239e60a3d663fdec5aa4af33f2a354afef36d34f0aefc","tests/test_pat.rs":"41776b878efae9b8e340f21ffe6296e921cf309f618482efd98609c33e32c28b","tests/test_precedence.rs":"71f3ea52cda8b40166bb7416fb98774e6a653542497b521f8e183e283dcf579d","tests/test_round_trip.rs":"e0de37f45fa223b488d25a41beab185eb92abb7bf765a9f13fe5d870ff31f5f1","tests/test_should_parse.rs":"4da4e25ee2baa7e75135c375042a7f958de136c5698dab03f99ff7a774dcd463","tests/test_size.rs":"970150b9d49ef91ab4c8f8c6a59b83f9a68a02acb779f0280733a5efaec6487a","tests/test_token_trees.rs":"a07ea657bf03b9c667c821b2db2af49b176ca737e3e01217a73cca78b7f11380","tests/zzz_stable.rs":"961d4940a926db4ca523d834b060c62de988e6a8e01c9f5efaa7bb4c86745b47"},"package":"66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"} -\ No newline at end of file -+{"files":{"Cargo.toml":"28ddb678a5ccac4423435384c8b7116f804e896eabc5aae9d5c2bc666aaebbb4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"03f3b53cf858536a0883aa5b5882ee61dcd0f1e71c0930c9106fcfa1d6aad2df","benches/file.rs":"b4724fc7c0f48b8f488e2632a1064f6c0bf16ded3969680fc3f4a2369536269b","benches/rust.rs":"ea6291ef2d2a83d94a3312fe179d48259f8ec0b04c961993ddd181d0a4ab740e","build.rs":"aeca2312f05aec658eaa66980a0ef3d578837db107a55702b39419ea0422eb4a","src/attr.rs":"7d79482634d6544eb4a4825405407b53660d0f5f8b929f7e1671e005b9d92038","src/await.rs":"18f0b2ecb319991f891e300011424985e3cf33d166ea9f29f22d575fc8c83a76","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"cf2a4b3bdc247b80c85ff5625a1dfb7a5f517fd835f6e1518a7b924990e4c293","src/custom_keyword.rs":"9627467063e41776315a6a14b2aaea3875592d8e0ebd2dc6df1fc2f12c06f146","src/custom_punctuation.rs":"b00e7bee96eb473507527e39db65e74e71592dc06421d2cfe45ed899c17d4847","src/data.rs":"7aec9a745cd53ec95688afa353f6efb9576e7fc0143757b51d28bc3d900b1d2a","src/derive.rs":"fa71866df6e383673dd3329f455a9f953585b83f9739050be3bf1f8c6d526b96","src/discouraged.rs":"a1f3d85e20dedf50b1b7b4571d970a3a6e9b2de4afde7dd0c986fe240df2ba46","src/error.rs":"c3005b50e3132026250c5356d0d391bf96db8087f0f5f744de98e360d8a20a3e","src/export.rs":"dcae67456278c0339acfbcbb4737b8d37cfba5a150ae789f31f4be79abf7e726","src/expr.rs":"54455fd20041996653ca5379b03cdf3c2fc1b3dd2e1149b5bc6b1dd492545d55","src/ext.rs":"870086d9021e6a6fcefa2f00cd91b55c4b74dcee8f0f6a07e76d96fb44707d61","src/file.rs":"75167ebc77e7870122078eabde1b872c337142d4b0962c20cedffcaaa2a5b7c6","src/gen/clone.rs":"0845c1bf8624c3f235cd247b4eb748e7e16b4c240097cb0ff16751f688c079ae","src/gen/debug.rs":"d24fe37f4ce1dd74f2dc54136e893782d3c4d0908323c036c97599551a56960c","src/gen/eq.rs":"1e6ef09b17ca7f36861ef23ce2a6991b231ed5f087f046469b5f23da40f5b419","src/gen/fold.rs":"3f59e59ed8ad2ab5dd347bfbe41bbc785c2aabd8ae902087a584a6daed597182","src/gen/hash.rs":"e5b2a52587173076777233a9e57e2b3c8e0dd6d6f41d16fa7c9fde68b05c2bfc","src/gen/visit.rs":"23008c170d4dd3975232876a0a654921d9b6af57372cb9fcc133ca740588d666","src/gen/visit_mut.rs":"42886c3ee02ded72d9c3eec006e20431eaee0c6b90ddefc1a36ec7bf50c6a24a","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"d1c175284ca21e777ef0414c28383929b170ccb00aaf7a929eb18d3b05e18da8","src/group.rs":"119b62d8481b4b1c327639bed40e114bf1969765250b68186628247fd4144b3b","src/ident.rs":"503156ce51a7ef0420892e8dbf2ecf8fe51f42a84d52cc2c05654e1a83020cbf","src/item.rs":"c9ad9881e8cda8ee3f157f0c7602fc53d08a7e3288b9afc388c393689eac5aea","src/lib.rs":"558ad13779233b27bebc4b2fc8025eb1c7e57b32130dc1dd911391e27b427500","src/lifetime.rs":"f390fe06692fc51fbf3eb490bb9f795da70e4452f51c5b0df3bbaa899084ddf1","src/lit.rs":"9fab84e38756b092fbb055dcdf01e31d42d916c49e3eaae8c9019043b0ee4301","src/lookahead.rs":"5cce8b4cb345a85c24a452ea6d78eadb76f01ca0a789cbf5ce35108334904173","src/mac.rs":"e5cecea397fd01a44958162781d8d94343fe2a1b9b9754a5666c3d2ab4d7ef64","src/macros.rs":"2ce05b553f14da4ee550bb681cb0733b7186ad94719cd36f96d53e15fd02cf2b","src/op.rs":"449514e146deab0ab020bc6f764544c294dbc780941c9802bf60cf1b2839d550","src/parse.rs":"bde888c98ee259f2a73489a693515ed4875432b0d79486ac83aea19f441992a3","src/parse_macro_input.rs":"653a020f023cac0eccbc1fcc34aa7bf80567b43e5475deab4ad3e487a5363201","src/parse_quote.rs":"642f21e5fa54df4b7c373fb158289ee1005d49e1a49b1d194df5438faee71c46","src/pat.rs":"1473b258162cc822f1ee0c0869f521053ed345a140c39ed83b9b4dfb6f9f2aca","src/path.rs":"f119f0c2af12fabd360eac9a2312e0f6e6c28c633c9671bde6ef0bece7c5ba3c","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"212f5a601d6c2eb8b8fa679be1167b455b595bee964d2775b0101ebb16c3eaa5","src/reserved.rs":"3625eb2a64589a4992ab79a1674e9679f465bea613ab139a671df5337e88cee6","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"7d77714d585e6f42397091ffb3a799fd7b20c05c5442c737683c429ea7d409a5","src/stmt.rs":"3917fbc897f80efe838267833c55650ff8d636cb49a6d1084e28eff65d0e3ccd","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"a1ca6298bf6592cb80cbab1db4eac2fa4e3fa56729bb807bfb0f08ab0f229ca5","src/tt.rs":"1cc9e200624288322f800f32e3d6e2e53da946467bb312dd40a52c02cdcc4730","src/ty.rs":"cb167cbb16240c59a31b44adec175172caaf75ffef9a0bb168584b51bf105795","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/.gitignore":"22e782449a3c216db3f7215d5fb8882e316768e40beeec3833aae419ad8941db","tests/common/eq.rs":"4b190a3833bdfd20a4cb1e3dff25a698751dec71d6f30249cf09426e061a4fb1","tests/common/mod.rs":"25ef6d7daa09bad3198a0e9e91b2812425f92db7c585c1e34a03a84d7362ccd8","tests/common/parse.rs":"8b7ba32f4988c30758c108536c4877dc5a039a237bf9b0687220ef2295797bbd","tests/debug/gen.rs":"d6e2abf2a7bb58a7895a60c2f094a98a4f85c9189d02011d0dcef6ef053f26e3","tests/debug/mod.rs":"868763d0ef1609a3ad5e05e9f1bfa0f813e91e7e9a36653414a188bb2fdaa425","tests/macros/mod.rs":"c0eafa4e3845fc08f6efe6021bac37822c0ac325eb7b51194a5f35236f648d92","tests/repo/mod.rs":"9e316b88d57ae213e81950c35e45443078ec90e702798353bc3528cb8a2810b6","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"610444351e3bf99366976bbf1da109c334a70ac9500caef366bcf9b68819829f","tests/test_expr.rs":"0ee83f6f6de950018c043efcc3e85776b4227dae3068309998a8d9709f2fc66c","tests/test_generics.rs":"9d713f90a79d6145efc89fb6f946029ca03486c632219950889da39940152ba0","tests/test_grouping.rs":"46c27baec4daaaf1e891892f0b0515ea8a44619071c7d0cc9192580916f1569f","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"461ed0c8648afffcea3217f52c9a88298182b4d39d73a11803b1281d99c98c25","tests/test_iterators.rs":"53ed6078d37550bd6765d2411e3660be401aef8a31a407350cc064a7d08c7c33","tests/test_lit.rs":"2a46c5f2f2ad1dcbb7e9b0cd11b55861c5ff818c2c4c51351d07e2daa7c74674","tests/test_meta.rs":"1fc98af3279cadc3d8db3c7e8d4d7f9e9dbd4d17548cf6a2f6f4536ed65367f6","tests/test_parse_buffer.rs":"8bbe2d24ca8a3788f72c6908fc96c26d546f11c69687bf8d72727f851d5e2d27","tests/test_parse_stream.rs":"2f449a2c41a3dee6fd14bee24e1666a453cb808eda17332fd91afd127fcdd2a6","tests/test_pat.rs":"2cb331fe404496d51e7cc7e283ae13c519a2265ca82e1c88e113296f860c2cba","tests/test_path.rs":"fcd5591e639fc787acc9763d828a811c8114525c9341282eefda8f331e082a51","tests/test_precedence.rs":"8d03656741b01e577d7501ce24332d1a4febec3e31a043e47c61062b8c527ed2","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"ba01bf4ec04cd2d6f9e4800c343563925ae960c5f16752dc0797fda4451b6cc2","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"5fae772bab66809d6708232f35cfb4a287882486763b0f763feec2ad79fbb68b","tests/test_stmt.rs":"17e4355843ee2982b51faba2721a18966f8c2b9422e16b052a123b8ee8b80752","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"5b7c0bfc4963d41920dd0b39fdea419e34f00409ba86ad4211d6c3c7e8bbe1c0","tests/test_visibility.rs":"3f958e2b3b5908005e756a80eea326a91eac97cc4ab60599bebde8d4b942d65c","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"} -\ No newline at end of file -diff --git a/third_party/rust/syn/Cargo.toml b/third_party/rust/syn/Cargo.toml ---- a/third_party/rust/syn/Cargo.toml -+++ b/third_party/rust/syn/Cargo.toml -@@ -8,79 +8,90 @@ - # If you believe there's an error in this file please file an - # issue against the rust-lang/cargo repository. If you're - # editing this file be aware that the upstream Cargo.toml - # will likely look very different (and much more reasonable) - - [package] - edition = "2018" - name = "syn" --version = "1.0.5" -+version = "1.0.40" - authors = ["David Tolnay "] - include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"] - description = "Parser for Rust source code" - documentation = "https://docs.rs/syn" - readme = "README.md" - categories = ["development-tools::procedural-macro-helpers"] - license = "MIT OR Apache-2.0" - repository = "https://github.com/dtolnay/syn" - [package.metadata.docs.rs] - all-features = true -+targets = ["x86_64-unknown-linux-gnu"] - - [package.metadata.playground] --all-features = true -- --[lib] --name = "syn" -+features = ["full", "visit", "visit-mut", "fold", "extra-traits"] - - [[bench]] - name = "rust" - harness = false - required-features = ["full", "parsing"] --edition = "2018" - - [[bench]] - name = "file" - required-features = ["full", "parsing"] --edition = "2018" - [dependencies.proc-macro2] --version = "1.0" -+version = "1.0.13" - default-features = false - - [dependencies.quote] - version = "1.0" - optional = true - default-features = false - - [dependencies.unicode-xid] - version = "0.2" -+[dev-dependencies.anyhow] -+version = "1.0" -+ -+[dev-dependencies.flate2] -+version = "1.0" -+ - [dev-dependencies.insta] --version = "0.9" -+version = "0.16" - - [dev-dependencies.rayon] - version = "1.0" - - [dev-dependencies.ref-cast] --version = "0.2" -+version = "1.0" - - [dev-dependencies.regex] - version = "1.0" - -+[dev-dependencies.reqwest] -+version = "0.10" -+features = ["blocking"] -+ -+[dev-dependencies.syn-test-suite] -+version = "0" -+ -+[dev-dependencies.tar] -+version = "0.4" -+ - [dev-dependencies.termcolor] - version = "1.0" - - [dev-dependencies.walkdir] - version = "2.1" - - [features] - clone-impls = [] - default = ["derive", "parsing", "printing", "clone-impls", "proc-macro"] - derive = [] - extra-traits = [] - fold = [] - full = [] - parsing = [] - printing = ["quote"] - proc-macro = ["proc-macro2/proc-macro", "quote/proc-macro"] -+test = ["syn-test-suite/all-features"] - visit = [] - visit-mut = [] --[badges.travis-ci] --repository = "dtolnay/syn" -diff --git a/third_party/rust/syn/README.md b/third_party/rust/syn/README.md ---- a/third_party/rust/syn/README.md -+++ b/third_party/rust/syn/README.md -@@ -1,15 +1,15 @@ - Parser for Rust source code - =========================== - --[![Build Status](https://api.travis-ci.org/dtolnay/syn.svg?branch=master)](https://travis-ci.org/dtolnay/syn) --[![Latest Version](https://img.shields.io/crates/v/syn.svg)](https://crates.io/crates/syn) --[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/syn/1.0/syn/) --[![Rustc Version 1.31+](https://img.shields.io/badge/rustc-1.31+-lightgray.svg)](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html) -+[github](https://github.com/dtolnay/syn) -+[crates.io](https://crates.io/crates/syn) -+[docs.rs](https://docs.rs/syn) -+[build status](https://github.com/dtolnay/syn/actions?query=branch%3Amaster) - - Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree - of Rust source code. - - Currently this library is geared toward use in Rust procedural macros, but - contains some APIs that may be useful more generally. - - - **Data structures** — Syn provides a complete syntax tree that can represent -@@ -41,20 +41,16 @@ contains some APIs that may be useful mo - - [`syn::File`]: https://docs.rs/syn/1.0/syn/struct.File.html - [`syn::Item`]: https://docs.rs/syn/1.0/syn/enum.Item.html - [`syn::Expr`]: https://docs.rs/syn/1.0/syn/enum.Expr.html - [`syn::Type`]: https://docs.rs/syn/1.0/syn/enum.Type.html - [`syn::DeriveInput`]: https://docs.rs/syn/1.0/syn/struct.DeriveInput.html - [parser functions]: https://docs.rs/syn/1.0/syn/parse/index.html - --If you get stuck with anything involving procedural macros in Rust I am happy to --provide help even if the issue is not related to Syn. Please file a ticket in --this repo. -- - *Version requirement: Syn supports rustc 1.31 and up.* - - [*Release notes*](https://github.com/dtolnay/syn/releases) - -
- - ## Resources - -@@ -83,18 +79,16 @@ tokens back to the compiler to compile i - syn = "1.0" - quote = "1.0" - - [lib] - proc-macro = true - ``` - - ```rust --extern crate proc_macro; -- - use proc_macro::TokenStream; - use quote::quote; - use syn::{parse_macro_input, DeriveInput}; - - #[proc_macro_derive(MyMacro)] - pub fn my_macro(input: TokenStream) -> TokenStream { - // Parse the input tokens into a syntax tree - let input = parse_macro_input!(input as DeriveInput); -@@ -266,17 +260,17 @@ incompatible ecosystems for proc macros - - In general all of your code should be written against proc-macro2 rather than - proc-macro. The one exception is in the signatures of procedural macro entry - points, which are required by the language to use `proc_macro::TokenStream`. - - The proc-macro2 crate will automatically detect and use the compiler's data - structures when a procedural macro is active. - --[proc-macro2]: https://docs.rs/proc-macro2/1.0.0/proc_macro2/ -+[proc-macro2]: https://docs.rs/proc-macro2/1.0/proc_macro2/ - -
- - #### License - - - Licensed under either of Apache License, Version - 2.0 or MIT license at your option. -diff --git a/third_party/rust/syn/benches/file.rs b/third_party/rust/syn/benches/file.rs ---- a/third_party/rust/syn/benches/file.rs -+++ b/third_party/rust/syn/benches/file.rs -@@ -1,14 +1,21 @@ - // $ cargo bench --features full --bench file - - #![feature(rustc_private, test)] -+#![recursion_limit = "1024"] - - extern crate test; - -+#[macro_use] -+#[path = "../tests/macros/mod.rs"] -+mod macros; -+ -+#[path = "../tests/common/mod.rs"] -+mod common; - #[path = "../tests/repo/mod.rs"] - pub mod repo; - - use proc_macro2::TokenStream; - use std::fs; - use std::str::FromStr; - use test::Bencher; - -diff --git a/third_party/rust/syn/benches/rust.rs b/third_party/rust/syn/benches/rust.rs ---- a/third_party/rust/syn/benches/rust.rs -+++ b/third_party/rust/syn/benches/rust.rs -@@ -1,15 +1,22 @@ - // $ cargo bench --features full --bench rust - // - // Syn only, useful for profiling: - // $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full --bench rust - - #![cfg_attr(not(syn_only), feature(rustc_private))] -+#![recursion_limit = "1024"] - -+#[macro_use] -+#[path = "../tests/macros/mod.rs"] -+mod macros; -+ -+#[path = "../tests/common/mod.rs"] -+mod common; - #[path = "../tests/repo/mod.rs"] - mod repo; - - use std::fs; - use std::time::{Duration, Instant}; - - #[cfg(not(syn_only))] - mod tokenstream_parse { -@@ -23,41 +30,45 @@ mod tokenstream_parse { - - mod syn_parse { - pub fn bench(content: &str) -> Result<(), ()> { - syn::parse_file(content).map(drop).map_err(drop) - } - } - - #[cfg(not(syn_only))] --mod libsyntax_parse { -+mod librustc_parse { - extern crate rustc_data_structures; -- extern crate syntax; -- extern crate syntax_pos; -+ extern crate rustc_errors; -+ extern crate rustc_parse; -+ extern crate rustc_session; -+ extern crate rustc_span; - - use rustc_data_structures::sync::Lrc; -- use syntax::edition::Edition; -- use syntax::errors::{emitter::Emitter, DiagnosticBuilder, Handler}; -- use syntax::parse::ParseSess; -- use syntax::source_map::{FilePathMapping, SourceMap}; -- use syntax_pos::FileName; -+ use rustc_errors::{emitter::Emitter, Diagnostic, Handler}; -+ use rustc_session::parse::ParseSess; -+ use rustc_span::source_map::{FilePathMapping, SourceMap}; -+ use rustc_span::{edition::Edition, FileName}; - - pub fn bench(content: &str) -> Result<(), ()> { - struct SilentEmitter; - - impl Emitter for SilentEmitter { -- fn emit_diagnostic(&mut self, _db: &DiagnosticBuilder) {} -+ fn emit_diagnostic(&mut self, _diag: &Diagnostic) {} -+ fn source_map(&self) -> Option<&Lrc> { -+ None -+ } - } - -- syntax::with_globals(Edition::Edition2018, || { -+ rustc_span::with_session_globals(Edition::Edition2018, || { - let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let emitter = Box::new(SilentEmitter); - let handler = Handler::with_emitter(false, None, emitter); - let sess = ParseSess::with_span_handler(handler, cm); -- if let Err(mut diagnostic) = syntax::parse::parse_crate_from_source_str( -+ if let Err(mut diagnostic) = rustc_parse::parse_crate_from_source_str( - FileName::Custom("bench".to_owned()), - content.to_owned(), - &sess, - ) { - diagnostic.cancel(); - return Err(()); - }; - Ok(()) -@@ -99,21 +110,21 @@ fn exec(mut codepath: impl FnMut(&str) - - assert_eq!(success, total); - begin.elapsed() - } - - fn main() { - repo::clone_rust(); - - macro_rules! testcases { -- ($($(#[$cfg:meta])* $name:path,)*) => { -+ ($($(#[$cfg:meta])* $name:ident,)*) => { - vec![ - $( - $(#[$cfg])* -- (stringify!($name), $name as fn(&str) -> Result<(), ()>), -+ (stringify!($name), $name::bench as fn(&str) -> Result<(), ()>), - )* - ] - }; - } - - #[cfg(not(syn_only))] - { - let mut lines = 0; -@@ -123,22 +134,22 @@ fn main() { - files += 1; - Ok(()) - }); - eprintln!("\n{} lines in {} files", lines, files); - } - - for (name, f) in testcases!( - #[cfg(not(syn_only))] -- read_from_disk::bench, -+ read_from_disk, - #[cfg(not(syn_only))] -- tokenstream_parse::bench, -- syn_parse::bench, -+ tokenstream_parse, -+ syn_parse, - #[cfg(not(syn_only))] -- libsyntax_parse::bench, -+ librustc_parse, - ) { - eprint!("{:20}", format!("{}:", name)); - let elapsed = exec(f); - eprintln!( - "elapsed={}.{:03}s", - elapsed.as_secs(), - elapsed.subsec_millis(), - ); -diff --git a/third_party/rust/syn/build.rs b/third_party/rust/syn/build.rs ---- a/third_party/rust/syn/build.rs -+++ b/third_party/rust/syn/build.rs -@@ -1,11 +1,11 @@ - use std::env; - use std::process::Command; --use std::str::{self, FromStr}; -+use std::str; - - // The rustc-cfg strings below are *not* public API. Please let us know by - // opening a GitHub issue if your build environment requires some way to enable - // these cfgs other than by executing our build script. - fn main() { - let compiler = match rustc_version() { - Some(compiler) => compiler, - None => return, -@@ -21,43 +21,19 @@ fn main() { - } - - struct Compiler { - minor: u32, - nightly: bool, - } - - fn rustc_version() -> Option { -- let rustc = match env::var_os("RUSTC") { -- Some(rustc) => rustc, -- None => return None, -- }; -- -- let output = match Command::new(rustc).arg("--version").output() { -- Ok(output) => output, -- Err(_) => return None, -- }; -- -- let version = match str::from_utf8(&output.stdout) { -- Ok(version) => version, -- Err(_) => return None, -- }; -- -+ let rustc = env::var_os("RUSTC")?; -+ let output = Command::new(rustc).arg("--version").output().ok()?; -+ let version = str::from_utf8(&output.stdout).ok()?; - let mut pieces = version.split('.'); - if pieces.next() != Some("rustc 1") { - return None; - } -- -- let next = match pieces.next() { -- Some(next) => next, -- None => return None, -- }; -- -- let minor = match u32::from_str(next) { -- Ok(minor) => minor, -- Err(_) => return None, -- }; -- -- Some(Compiler { -- minor: minor, -- nightly: version.contains("nightly"), -- }) -+ let minor = pieces.next()?.parse().ok()?; -+ let nightly = version.contains("nightly"); -+ Some(Compiler { minor, nightly }) - } -diff --git a/third_party/rust/syn/src/attr.rs b/third_party/rust/syn/src/attr.rs ---- a/third_party/rust/syn/src/attr.rs -+++ b/third_party/rust/syn/src/attr.rs -@@ -4,25 +4,21 @@ use crate::punctuated::Punctuated; - use std::iter; - - use proc_macro2::TokenStream; - - #[cfg(feature = "parsing")] - use crate::parse::{Parse, ParseBuffer, ParseStream, Parser, Result}; - #[cfg(feature = "parsing")] - use crate::punctuated::Pair; --#[cfg(feature = "extra-traits")] --use crate::tt::TokenStreamHelper; --#[cfg(feature = "extra-traits")] --use std::hash::{Hash, Hasher}; - - ast_struct! { - /// An attribute like `#[repr(transparent)]`. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` - /// feature.* - /// - ///
- /// - /// # Syntax - /// - /// Rust has six types of attributes. - /// -@@ -106,58 +102,69 @@ ast_struct! { - /// If the attribute you are parsing is expected to conform to the - /// conventional structured form of attribute, use [`parse_meta()`] to - /// obtain that structured representation. If the attribute follows some - /// other grammar of its own, use [`parse_args()`] to parse that into the - /// expected data structure. - /// - /// [`parse_meta()`]: Attribute::parse_meta - /// [`parse_args()`]: Attribute::parse_args -- pub struct Attribute #manual_extra_traits { -+ /// -+ ///


-+ /// -+ /// # Doc comments -+ /// -+ /// The compiler transforms doc comments, such as `/// comment` and `/*! -+ /// comment */`, into attributes before macros are expanded. Each comment is -+ /// expanded into an attribute of the form `#[doc = r"comment"]`. -+ /// -+ /// As an example, the following `mod` items are expanded identically: -+ /// -+ /// ``` -+ /// # use syn::{ItemMod, parse_quote}; -+ /// let doc: ItemMod = parse_quote! { -+ /// /// Single line doc comments -+ /// /// We write so many! -+ /// /** -+ /// * Multi-line comments... -+ /// * May span many lines -+ /// */ -+ /// mod example { -+ /// //! Of course, they can be inner too -+ /// /*! And fit in a single line */ -+ /// } -+ /// }; -+ /// let attr: ItemMod = parse_quote! { -+ /// #[doc = r" Single line doc comments"] -+ /// #[doc = r" We write so many!"] -+ /// #[doc = r" -+ /// * Multi-line comments... -+ /// * May span many lines -+ /// "] -+ /// mod example { -+ /// #![doc = r" Of course, they can be inner too"] -+ /// #![doc = r" And fit in a single line "] -+ /// } -+ /// }; -+ /// assert_eq!(doc, attr); -+ /// ``` -+ pub struct Attribute { - pub pound_token: Token![#], - pub style: AttrStyle, - pub bracket_token: token::Bracket, - pub path: Path, - pub tokens: TokenStream, - } - } - --#[cfg(feature = "extra-traits")] --impl Eq for Attribute {} -- --#[cfg(feature = "extra-traits")] --impl PartialEq for Attribute { -- fn eq(&self, other: &Self) -> bool { -- self.style == other.style -- && self.pound_token == other.pound_token -- && self.bracket_token == other.bracket_token -- && self.path == other.path -- && TokenStreamHelper(&self.tokens) == TokenStreamHelper(&other.tokens) -- } --} -- --#[cfg(feature = "extra-traits")] --impl Hash for Attribute { -- fn hash(&self, state: &mut H) -- where -- H: Hasher, -- { -- self.style.hash(state); -- self.pound_token.hash(state); -- self.bracket_token.hash(state); -- self.path.hash(state); -- TokenStreamHelper(&self.tokens).hash(state); -- } --} -- - impl Attribute { - /// Parses the content of the attribute, consisting of the path and tokens, - /// as a [`Meta`] if possible. - /// -- /// *This function is available if Syn is built with the `"parsing"` -+ /// *This function is available only if Syn is built with the `"parsing"` - /// feature.* - #[cfg(feature = "parsing")] - pub fn parse_meta(&self) -> Result { - fn clone_ident_segment(segment: &PathSegment) -> PathSegment { - PathSegment { - ident: segment.ident.clone(), - arguments: PathArguments::None, - } -@@ -194,91 +201,95 @@ impl Attribute { - /// parser; and - /// - the error message has a more useful span when `tokens` is empty. - /// - /// ```text - /// #[my_attr(value < 5)] - /// ^^^^^^^^^ what gets parsed - /// ``` - /// -- /// *This function is available if Syn is built with the `"parsing"` -+ /// *This function is available only if Syn is built with the `"parsing"` - /// feature.* - #[cfg(feature = "parsing")] - pub fn parse_args(&self) -> Result { - self.parse_args_with(T::parse) - } - - /// Parse the arguments to the attribute using the given parser. - /// -- /// *This function is available if Syn is built with the `"parsing"` -+ /// *This function is available only if Syn is built with the `"parsing"` - /// feature.* - #[cfg(feature = "parsing")] - pub fn parse_args_with(&self, parser: F) -> Result { - let parser = |input: ParseStream| { - let args = enter_args(self, input)?; - parse::parse_stream(parser, &args) - }; - parser.parse2(self.tokens.clone()) - } - - /// Parses zero or more outer attributes from the stream. - /// -- /// *This function is available if Syn is built with the `"parsing"` -+ /// *This function is available only if Syn is built with the `"parsing"` - /// feature.* - #[cfg(feature = "parsing")] - pub fn parse_outer(input: ParseStream) -> Result> { - let mut attrs = Vec::new(); - while input.peek(Token![#]) { - attrs.push(input.call(parsing::single_parse_outer)?); - } - Ok(attrs) - } - - /// Parses zero or more inner attributes from the stream. - /// -- /// *This function is available if Syn is built with the `"parsing"` -+ /// *This function is available only if Syn is built with the `"parsing"` - /// feature.* - #[cfg(feature = "parsing")] - pub fn parse_inner(input: ParseStream) -> Result> { - let mut attrs = Vec::new(); - while input.peek(Token![#]) && input.peek2(Token![!]) { - attrs.push(input.call(parsing::single_parse_inner)?); - } - Ok(attrs) - } - } - - #[cfg(feature = "parsing")] --fn error_expected_args(attr: &Attribute) -> Error { -+fn expected_parentheses(attr: &Attribute) -> String { - let style = match attr.style { - AttrStyle::Outer => "#", - AttrStyle::Inner(_) => "#!", - }; - - let mut path = String::new(); - for segment in &attr.path.segments { - if !path.is_empty() || attr.path.leading_colon.is_some() { - path += "::"; - } - path += &segment.ident.to_string(); - } - -- let msg = format!("expected attribute arguments: {}[{}(...)]", style, path); -- -- #[cfg(feature = "printing")] -- return Error::new_spanned(attr, msg); -- -- #[cfg(not(feature = "printing"))] -- return Error::new(attr.bracket_token.span, msg); -+ format!("{}[{}(...)]", style, path) - } - - #[cfg(feature = "parsing")] - fn enter_args<'a>(attr: &Attribute, input: ParseStream<'a>) -> Result> { - if input.is_empty() { -- return Err(error_expected_args(attr)); -+ let expected = expected_parentheses(attr); -+ let msg = format!("expected attribute arguments in parentheses: {}", expected); -+ return Err(crate::error::new2( -+ attr.pound_token.span, -+ attr.bracket_token.span, -+ msg, -+ )); -+ } else if input.peek(Token![=]) { -+ let expected = expected_parentheses(attr); -+ let msg = format!("expected parentheses: {}", expected); -+ return Err(input.error(msg)); - }; - - let content; - if input.peek(token::Paren) { - parenthesized!(content in input); - } else if input.peek(token::Bracket) { - bracketed!(content in input); - } else if input.peek(token::Brace) { -@@ -293,41 +304,40 @@ fn enter_args<'a>(attr: &Attribute, inpu - Err(input.error("unexpected token in attribute arguments")) - } - } - - ast_enum! { - /// Distinguishes between attributes that decorate an item and attributes - /// that are contained within an item. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` - /// feature.* - /// - /// # Outer attributes - /// - /// - `#[repr(transparent)]` - /// - `/// # Example` - /// - `/** Please file an issue */` - /// - /// # Inner attributes - /// - /// - `#![feature(proc_macro)]` - /// - `//! # Example` - /// - `/*! Please file an issue */` -- #[cfg_attr(feature = "clone-impls", derive(Copy))] - pub enum AttrStyle { - Outer, - Inner(Token![!]), - } - } - - ast_enum_of_structs! { - /// Content of a compile-time structured attribute. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` - /// feature.* - /// - /// ## Path - /// - /// A meta path is like the `test` in `#[test]`. - /// - /// ## List - /// -@@ -355,29 +365,29 @@ ast_enum_of_structs! { - /// A name-value pair within an attribute, like `feature = "nightly"`. - NameValue(MetaNameValue), - } - } - - ast_struct! { - /// A structured list within an attribute, like `derive(Copy, Clone)`. - /// -- /// *This type is available if Syn is built with the `"derive"` or -+ /// *This type is available only if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct MetaList { - pub path: Path, - pub paren_token: token::Paren, - pub nested: Punctuated, - } - } - - ast_struct! { - /// A name-value pair within an attribute, like `feature = "nightly"`. - /// -- /// *This type is available if Syn is built with the `"derive"` or -+ /// *This type is available only if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct MetaNameValue { - pub path: Path, - pub eq_token: Token![=], - pub lit: Lit, - } - } - -@@ -393,17 +403,17 @@ impl Meta { - Meta::NameValue(meta) => &meta.path, - } - } - } - - ast_enum_of_structs! { - /// Element of a compile-time attribute list. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` - /// feature.* - pub enum NestedMeta { - /// A structured meta item, like the `Copy` in `#[derive(Copy)]` which - /// would be a nested `Meta::Path`. - Meta(Meta), - - /// A Rust literal, like the `"new_name"` in `#[rename("new_name")]`. - Lit(Lit), -@@ -424,18 +434,18 @@ ast_enum_of_structs! { - /// /* ... */ - /// } - /// ``` - /// - /// The implementation of this macro would want to parse its attribute arguments - /// as type `AttributeArgs`. - /// - /// ``` --/// extern crate proc_macro; --/// -+/// # extern crate proc_macro; -+/// # - /// use proc_macro::TokenStream; - /// use syn::{parse_macro_input, AttributeArgs, ItemFn}; - /// - /// # const IGNORE: &str = stringify! { - /// #[proc_macro_attribute] - /// # }; - /// pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream { - /// let args = parse_macro_input!(args as AttributeArgs); -@@ -459,27 +469,27 @@ where - T: IntoIterator, - { - type Ret = iter::Filter bool>; - - fn outer(self) -> Self::Ret { - fn is_outer(attr: &&Attribute) -> bool { - match attr.style { - AttrStyle::Outer => true, -- _ => false, -+ AttrStyle::Inner(_) => false, - } - } - self.into_iter().filter(is_outer) - } - - fn inner(self) -> Self::Ret { - fn is_inner(attr: &&Attribute) -> bool { - match attr.style { - AttrStyle::Inner(_) => true, -- _ => false, -+ AttrStyle::Outer => false, - } - } - self.into_iter().filter(is_inner) - } - } - - #[cfg(feature = "parsing")] - pub mod parsing { -diff --git a/third_party/rust/syn/src/buffer.rs b/third_party/rust/syn/src/buffer.rs ---- a/third_party/rust/syn/src/buffer.rs -+++ b/third_party/rust/syn/src/buffer.rs -@@ -1,12 +1,12 @@ - //! A stably addressed token buffer supporting efficient traversal based on a - //! cheaply copyable cursor. - //! --//! *This module is available if Syn is built with the `"parsing"` feature.* -+//! *This module is available only if Syn is built with the `"parsing"` feature.* - - // This module is heavily commented as it contains most of the unsafe code in - // Syn, and caution should be used when editing it. The public-facing interface - // is 100% safe but the implementation is fragile internally. - - #[cfg(all( - not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))), - feature = "proc-macro" -@@ -31,17 +31,17 @@ enum Entry { - // token tree, or null if this is the outermost level. - End(*const Entry), - } - - /// A buffer that can be efficiently traversed multiple times, unlike - /// `TokenStream` which requires a deep copy in order to traverse more than - /// once. - /// --/// *This type is available if Syn is built with the `"parsing"` feature.* -+/// *This type is available only if Syn is built with the `"parsing"` feature.* - pub struct TokenBuffer { - // NOTE: Do not derive clone on this - there are raw pointers inside which - // will be messed up. Moving the `TokenBuffer` itself is safe as the actual - // backing slices won't be moved. - data: Box<[Entry]>, - } - - impl TokenBuffer { -@@ -93,17 +93,17 @@ impl TokenBuffer { - } - - TokenBuffer { data: entries } - } - - /// Creates a `TokenBuffer` containing all the tokens from the input - /// `TokenStream`. - /// -- /// *This method is available if Syn is built with both the `"parsing"` and -+ /// *This method is available only if Syn is built with both the `"parsing"` and - /// `"proc-macro"` features.* - #[cfg(all( - not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))), - feature = "proc-macro" - ))] - pub fn new(stream: pm::TokenStream) -> TokenBuffer { - Self::new2(stream.into()) - } -@@ -128,18 +128,17 @@ impl TokenBuffer { - /// and copied around. - /// - /// An empty `Cursor` can be created directly, or one may create a `TokenBuffer` - /// object and get a cursor to its first token with `begin()`. - /// - /// Two cursors are equal if they have the same location in the same input - /// stream, and have the same scope. - /// --/// *This type is available if Syn is built with the `"parsing"` feature.* --#[derive(Copy, Clone, Eq, PartialEq)] -+/// *This type is available only if Syn is built with the `"parsing"` feature.* - pub struct Cursor<'a> { - // The current entry which the `Cursor` is pointing at. - ptr: *const Entry, - // This is the only `Entry::End(..)` object which this cursor is allowed to - // point at. All other `End` objects are skipped over in `Cursor::create`. - scope: *const Entry, - // Cursor is covariant in 'a. This field ensures that our pointers are still - // valid. -@@ -196,37 +195,38 @@ impl<'a> Cursor<'a> { - - /// Bump the cursor to point at the next token after the current one. This - /// is undefined behavior if the cursor is currently looking at an - /// `Entry::End`. - unsafe fn bump(self) -> Cursor<'a> { - Cursor::create(self.ptr.offset(1), self.scope) - } - -- /// If the cursor is looking at a `None`-delimited group, move it to look at -- /// the first token inside instead. If the group is empty, this will move -+ /// While the cursor is looking at a `None`-delimited group, move it to look -+ /// at the first token inside instead. If the group is empty, this will move - /// the cursor past the `None`-delimited group. - /// - /// WARNING: This mutates its argument. - fn ignore_none(&mut self) { -- if let Entry::Group(group, buf) = self.entry() { -+ while let Entry::Group(group, buf) = self.entry() { - if group.delimiter() == Delimiter::None { - // NOTE: We call `Cursor::create` here to make sure that - // situations where we should immediately exit the span after - // entering it are handled correctly. - unsafe { - *self = Cursor::create(&buf.data[0], self.scope); - } -+ } else { -+ break; - } - } - } - - /// Checks whether the cursor is currently pointing at the end of its valid - /// scope. -- #[inline] - pub fn eof(self) -> bool { - // We're at eof if we're at the end of our scope. - self.ptr == self.scope - } - - /// If the cursor is pointing at a `Group` with the given delimiter, returns - /// a cursor into that group and one pointing to the next `TokenTree`. - pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> { -@@ -337,16 +337,54 @@ impl<'a> Cursor<'a> { - match self.entry() { - Entry::Group(group, _) => group.span(), - Entry::Literal(l) => l.span(), - Entry::Ident(t) => t.span(), - Entry::Punct(o) => o.span(), - Entry::End(..) => Span::call_site(), - } - } -+ -+ /// Skip over the next token without cloning it. Returns `None` if this -+ /// cursor points to eof. -+ /// -+ /// This method treats `'lifetimes` as a single token. -+ pub(crate) fn skip(self) -> Option> { -+ match self.entry() { -+ Entry::End(..) => None, -+ -+ // Treat lifetimes as a single tt for the purposes of 'skip'. -+ Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => { -+ let next = unsafe { self.bump() }; -+ match next.entry() { -+ Entry::Ident(_) => Some(unsafe { next.bump() }), -+ _ => Some(next), -+ } -+ } -+ _ => Some(unsafe { self.bump() }), -+ } -+ } -+} -+ -+impl<'a> Copy for Cursor<'a> {} -+ -+impl<'a> Clone for Cursor<'a> { -+ fn clone(&self) -> Self { -+ *self -+ } -+} -+ -+impl<'a> Eq for Cursor<'a> {} -+ -+impl<'a> PartialEq for Cursor<'a> { -+ fn eq(&self, other: &Self) -> bool { -+ let Cursor { ptr, scope, marker } = self; -+ let _ = marker; -+ *ptr == other.ptr && *scope == other.scope -+ } - } - - pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool { - a.scope == b.scope - } - - pub(crate) fn open_span_of_group(cursor: Cursor) -> Span { - match cursor.entry() { -diff --git a/third_party/rust/syn/src/custom_keyword.rs b/third_party/rust/syn/src/custom_keyword.rs ---- a/third_party/rust/syn/src/custom_keyword.rs -+++ b/third_party/rust/syn/src/custom_keyword.rs -@@ -81,46 +81,46 @@ - /// value: input.parse()?, - /// }) - /// } else { - /// Err(lookahead.error()) - /// } - /// } - /// } - /// ``` --#[macro_export(local_inner_macros)] -+#[macro_export] - macro_rules! custom_keyword { - ($ident:ident) => { - #[allow(non_camel_case_types)] - pub struct $ident { - pub span: $crate::export::Span, - } - - #[doc(hidden)] -- #[allow(non_snake_case)] -+ #[allow(dead_code, non_snake_case)] - pub fn $ident<__S: $crate::export::IntoSpans<[$crate::export::Span; 1]>>( - span: __S, - ) -> $ident { - $ident { - span: $crate::export::IntoSpans::into_spans(span)[0], - } - } - - impl $crate::export::Default for $ident { - fn default() -> Self { - $ident { - span: $crate::export::Span::call_site(), - } - } - } - -- impl_parse_for_custom_keyword!($ident); -- impl_to_tokens_for_custom_keyword!($ident); -- impl_clone_for_custom_keyword!($ident); -- impl_extra_traits_for_custom_keyword!($ident); -+ $crate::impl_parse_for_custom_keyword!($ident); -+ $crate::impl_to_tokens_for_custom_keyword!($ident); -+ $crate::impl_clone_for_custom_keyword!($ident); -+ $crate::impl_extra_traits_for_custom_keyword!($ident); - }; - } - - // Not public API. - #[cfg(feature = "parsing")] - #[doc(hidden)] - #[macro_export] - macro_rules! impl_parse_for_custom_keyword { -diff --git a/third_party/rust/syn/src/custom_punctuation.rs b/third_party/rust/syn/src/custom_punctuation.rs ---- a/third_party/rust/syn/src/custom_punctuation.rs -+++ b/third_party/rust/syn/src/custom_punctuation.rs -@@ -69,67 +69,67 @@ - /// Ok(tokens) - /// } - /// - /// fn main() { - /// let input = r#" a::b c::d::e "#; - /// let _: PathSegments = syn::parse_str(input).unwrap(); - /// } - /// ``` --#[macro_export(local_inner_macros)] -+#[macro_export] - macro_rules! custom_punctuation { - ($ident:ident, $($tt:tt)+) => { - pub struct $ident { -- pub spans: custom_punctuation_repr!($($tt)+), -+ pub spans: $crate::custom_punctuation_repr!($($tt)+), - } - - #[doc(hidden)] -- #[allow(non_snake_case)] -- pub fn $ident<__S: $crate::export::IntoSpans>( -+ #[allow(dead_code, non_snake_case)] -+ pub fn $ident<__S: $crate::export::IntoSpans<$crate::custom_punctuation_repr!($($tt)+)>>( - spans: __S, - ) -> $ident { -- let _validate_len = 0 $(+ custom_punctuation_len!(strict, $tt))*; -+ let _validate_len = 0 $(+ $crate::custom_punctuation_len!(strict, $tt))*; - $ident { - spans: $crate::export::IntoSpans::into_spans(spans) - } - } - - impl $crate::export::Default for $ident { - fn default() -> Self { - $ident($crate::export::Span::call_site()) - } - } - -- impl_parse_for_custom_punctuation!($ident, $($tt)+); -- impl_to_tokens_for_custom_punctuation!($ident, $($tt)+); -- impl_clone_for_custom_punctuation!($ident, $($tt)+); -- impl_extra_traits_for_custom_punctuation!($ident, $($tt)+); -+ $crate::impl_parse_for_custom_punctuation!($ident, $($tt)+); -+ $crate::impl_to_tokens_for_custom_punctuation!($ident, $($tt)+); -+ $crate::impl_clone_for_custom_punctuation!($ident, $($tt)+); -+ $crate::impl_extra_traits_for_custom_punctuation!($ident, $($tt)+); - }; - } - - // Not public API. - #[cfg(feature = "parsing")] - #[doc(hidden)] --#[macro_export(local_inner_macros)] -+#[macro_export] - macro_rules! impl_parse_for_custom_punctuation { - ($ident:ident, $($tt:tt)+) => { - impl $crate::token::CustomToken for $ident { - fn peek(cursor: $crate::buffer::Cursor) -> bool { -- $crate::token::parsing::peek_punct(cursor, stringify_punct!($($tt)+)) -+ $crate::token::parsing::peek_punct(cursor, $crate::stringify_punct!($($tt)+)) - } - - fn display() -> &'static $crate::export::str { -- custom_punctuation_concat!("`", stringify_punct!($($tt)+), "`") -+ concat!("`", $crate::stringify_punct!($($tt)+), "`") - } - } - - impl $crate::parse::Parse for $ident { - fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> { -- let spans: custom_punctuation_repr!($($tt)+) = -- $crate::token::parsing::punct(input, stringify_punct!($($tt)+))?; -+ let spans: $crate::custom_punctuation_repr!($($tt)+) = -+ $crate::token::parsing::punct(input, $crate::stringify_punct!($($tt)+))?; - Ok($ident(spans)) - } - } - }; - } - - // Not public API. - #[cfg(not(feature = "parsing"))] -@@ -137,22 +137,22 @@ macro_rules! impl_parse_for_custom_punct - #[macro_export] - macro_rules! impl_parse_for_custom_punctuation { - ($ident:ident, $($tt:tt)+) => {}; - } - - // Not public API. - #[cfg(feature = "printing")] - #[doc(hidden)] --#[macro_export(local_inner_macros)] -+#[macro_export] - macro_rules! impl_to_tokens_for_custom_punctuation { - ($ident:ident, $($tt:tt)+) => { - impl $crate::export::ToTokens for $ident { - fn to_tokens(&self, tokens: &mut $crate::export::TokenStream2) { -- $crate::token::printing::punct(stringify_punct!($($tt)+), &self.spans, tokens) -+ $crate::token::printing::punct($crate::stringify_punct!($($tt)+), &self.spans, tokens) - } - } - }; - } - - // Not public API. - #[cfg(not(feature = "printing"))] - #[doc(hidden)] -@@ -216,26 +216,26 @@ macro_rules! impl_extra_traits_for_custo - #[doc(hidden)] - #[macro_export] - macro_rules! impl_extra_traits_for_custom_punctuation { - ($ident:ident, $($tt:tt)+) => {}; - } - - // Not public API. - #[doc(hidden)] --#[macro_export(local_inner_macros)] -+#[macro_export] - macro_rules! custom_punctuation_repr { - ($($tt:tt)+) => { -- [$crate::export::Span; 0 $(+ custom_punctuation_len!(lenient, $tt))+] -+ [$crate::export::Span; 0 $(+ $crate::custom_punctuation_len!(lenient, $tt))+] - }; - } - - // Not public API. - #[doc(hidden)] --#[macro_export(local_inner_macros)] -+#[macro_export] - #[rustfmt::skip] - macro_rules! custom_punctuation_len { - ($mode:ident, +) => { 1 }; - ($mode:ident, +=) => { 2 }; - ($mode:ident, &) => { 1 }; - ($mode:ident, &&) => { 2 }; - ($mode:ident, &=) => { 2 }; - ($mode:ident, @) => { 1 }; -@@ -274,17 +274,17 @@ macro_rules! custom_punctuation_len { - ($mode:ident, <<=) => { 3 }; - ($mode:ident, >>) => { 2 }; - ($mode:ident, >>=) => { 3 }; - ($mode:ident, *) => { 1 }; - ($mode:ident, -) => { 1 }; - ($mode:ident, -=) => { 2 }; - ($mode:ident, ~) => { 1 }; - (lenient, $tt:tt) => { 0 }; -- (strict, $tt:tt) => {{ custom_punctuation_unexpected!($tt); 0 }}; -+ (strict, $tt:tt) => {{ $crate::custom_punctuation_unexpected!($tt); 0 }}; - } - - // Not public API. - #[doc(hidden)] - #[macro_export] - macro_rules! custom_punctuation_unexpected { - () => {}; - } -@@ -292,18 +292,8 @@ macro_rules! custom_punctuation_unexpect - // Not public API. - #[doc(hidden)] - #[macro_export] - macro_rules! stringify_punct { - ($($tt:tt)+) => { - concat!($(stringify!($tt)),+) - }; - } -- --// Not public API. --// Without this, local_inner_macros breaks when looking for concat! --#[doc(hidden)] --#[macro_export] --macro_rules! custom_punctuation_concat { -- ($($tt:tt)*) => { -- concat!($($tt)*) -- }; --} -diff --git a/third_party/rust/syn/src/data.rs b/third_party/rust/syn/src/data.rs ---- a/third_party/rust/syn/src/data.rs -+++ b/third_party/rust/syn/src/data.rs -@@ -1,15 +1,15 @@ - use super::*; - use crate::punctuated::Punctuated; - - ast_struct! { - /// An enum variant. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` - /// feature.* - pub struct Variant { - /// Attributes tagged on the variant. - pub attrs: Vec, - - /// Name of the variant. - pub ident: Ident, - -@@ -19,17 +19,17 @@ ast_struct! { - /// Explicit discriminant: `Variant = 1` - pub discriminant: Option<(Token![=], Expr)>, - } - } - - ast_enum_of_structs! { - /// Data stored within an enum variant or struct. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` - /// feature.* - /// - /// # Syntax tree enum - /// - /// This type is a [syntax tree enum]. - /// - /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums - // -@@ -47,28 +47,28 @@ ast_enum_of_structs! { - Unit, - } - } - - ast_struct! { - /// Named fields of a struct or struct variant such as `Point { x: f64, - /// y: f64 }`. - /// -- /// *This type is available if Syn is built with the `"derive"` or -+ /// *This type is available only if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct FieldsNamed { - pub brace_token: token::Brace, - pub named: Punctuated, - } - } - - ast_struct! { - /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. - /// -- /// *This type is available if Syn is built with the `"derive"` or -+ /// *This type is available only if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct FieldsUnnamed { - pub paren_token: token::Paren, - pub unnamed: Punctuated, - } - } - - impl Fields { -@@ -88,16 +88,34 @@ impl Fields { - /// struct or variant's fields uniformly. - pub fn iter_mut(&mut self) -> punctuated::IterMut { - match self { - Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(), - Fields::Named(f) => f.named.iter_mut(), - Fields::Unnamed(f) => f.unnamed.iter_mut(), - } - } -+ -+ /// Returns the number of fields. -+ pub fn len(&self) -> usize { -+ match self { -+ Fields::Unit => 0, -+ Fields::Named(f) => f.named.len(), -+ Fields::Unnamed(f) => f.unnamed.len(), -+ } -+ } -+ -+ /// Returns `true` if there are zero fields. -+ pub fn is_empty(&self) -> bool { -+ match self { -+ Fields::Unit => true, -+ Fields::Named(f) => f.named.is_empty(), -+ Fields::Unnamed(f) => f.unnamed.is_empty(), -+ } -+ } - } - - impl IntoIterator for Fields { - type Item = Field; - type IntoIter = punctuated::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - match self { -@@ -124,17 +142,17 @@ impl<'a> IntoIterator for &'a mut Fields - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } - } - - ast_struct! { - /// A field of a struct or enum variant. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` - /// feature.* - pub struct Field { - /// Attributes tagged on the field. - pub attrs: Vec, - - /// Visibility of the field. - pub vis: Visibility, - -@@ -149,17 +167,17 @@ ast_struct! { - pub ty: Type, - } - } - - ast_enum_of_structs! { - /// The visibility level of an item: inherited or `pub` or - /// `pub(restricted)`. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` - /// feature.* - /// - /// # Syntax tree enum - /// - /// This type is a [syntax tree enum]. - /// - /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums - // -@@ -179,58 +197,61 @@ ast_enum_of_structs! { - /// An inherited visibility, which usually means private. - Inherited, - } - } - - ast_struct! { - /// A public visibility level: `pub`. - /// -- /// *This type is available if Syn is built with the `"derive"` or -+ /// *This type is available only if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct VisPublic { - pub pub_token: Token![pub], - } - } - - ast_struct! { - /// A crate-level visibility: `crate`. - /// -- /// *This type is available if Syn is built with the `"derive"` or -+ /// *This type is available only if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct VisCrate { - pub crate_token: Token![crate], - } - } - - ast_struct! { - /// A visibility level restricted to some path: `pub(self)` or - /// `pub(super)` or `pub(crate)` or `pub(in some::module)`. - /// -- /// *This type is available if Syn is built with the `"derive"` or -+ /// *This type is available only if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct VisRestricted { - pub pub_token: Token![pub], - pub paren_token: token::Paren, - pub in_token: Option, - pub path: Box, - } - } - - #[cfg(feature = "parsing")] - pub mod parsing { - use super::*; - - use crate::ext::IdentExt; -+ use crate::parse::discouraged::Speculative; - use crate::parse::{Parse, ParseStream, Result}; - - impl Parse for Variant { - fn parse(input: ParseStream) -> Result { -+ let attrs = input.call(Attribute::parse_outer)?; -+ let _visibility: Visibility = input.parse()?; - Ok(Variant { -- attrs: input.call(Attribute::parse_outer)?, -+ attrs, - ident: input.parse()?, - fields: { - if input.peek(token::Brace) { - Fields::Named(input.parse()?) - } else if input.peek(token::Paren) { - Fields::Unnamed(input.parse()?) - } else { - Fields::Unit -@@ -290,68 +311,99 @@ pub mod parsing { - colon_token: None, - ty: input.parse()?, - }) - } - } - - impl Parse for Visibility { - fn parse(input: ParseStream) -> Result { -+ // Recognize an empty None-delimited group, as produced by a $:vis -+ // matcher that matched no tokens. -+ if input.peek(token::Group) { -+ let ahead = input.fork(); -+ let group = crate::group::parse_group(&ahead)?; -+ if group.content.is_empty() { -+ input.advance_to(&ahead); -+ return Ok(Visibility::Inherited); -+ } -+ } -+ - if input.peek(Token![pub]) { - Self::parse_pub(input) - } else if input.peek(Token![crate]) { - Self::parse_crate(input) - } else { - Ok(Visibility::Inherited) - } - } - } - - impl Visibility { - fn parse_pub(input: ParseStream) -> Result { - let pub_token = input.parse::()?; - - if input.peek(token::Paren) { -- // TODO: optimize using advance_to - let ahead = input.fork(); -- let mut content; -- parenthesized!(content in ahead); - -+ let content; -+ let paren_token = parenthesized!(content in ahead); - if content.peek(Token![crate]) - || content.peek(Token![self]) - || content.peek(Token![super]) - { -+ let path = content.call(Ident::parse_any)?; -+ -+ // Ensure there are no additional tokens within `content`. -+ // Without explicitly checking, we may misinterpret a tuple -+ // field as a restricted visibility, causing a parse error. -+ // e.g. `pub (crate::A, crate::B)` (Issue #720). -+ if content.is_empty() { -+ input.advance_to(&ahead); -+ return Ok(Visibility::Restricted(VisRestricted { -+ pub_token, -+ paren_token, -+ in_token: None, -+ path: Box::new(Path::from(path)), -+ })); -+ } -+ } else if content.peek(Token![in]) { -+ let in_token: Token![in] = content.parse()?; -+ let path = content.call(Path::parse_mod_style)?; -+ -+ input.advance_to(&ahead); - return Ok(Visibility::Restricted(VisRestricted { - pub_token, -- paren_token: parenthesized!(content in input), -- in_token: None, -- path: Box::new(Path::from(content.call(Ident::parse_any)?)), -- })); -- } else if content.peek(Token![in]) { -- return Ok(Visibility::Restricted(VisRestricted { -- pub_token, -- paren_token: parenthesized!(content in input), -- in_token: Some(content.parse()?), -- path: Box::new(content.call(Path::parse_mod_style)?), -+ paren_token, -+ in_token: Some(in_token), -+ path: Box::new(path), - })); - } - } - - Ok(Visibility::Public(VisPublic { pub_token })) - } - - fn parse_crate(input: ParseStream) -> Result { - if input.peek2(Token![::]) { - Ok(Visibility::Inherited) - } else { - Ok(Visibility::Crate(VisCrate { - crate_token: input.parse()?, - })) - } - } -+ -+ #[cfg(feature = "full")] -+ pub(crate) fn is_some(&self) -> bool { -+ match self { -+ Visibility::Inherited => false, -+ _ => true, -+ } -+ } - } - } - - #[cfg(feature = "printing")] - mod printing { - use super::*; - - use proc_macro2::TokenStream; -diff --git a/third_party/rust/syn/src/derive.rs b/third_party/rust/syn/src/derive.rs ---- a/third_party/rust/syn/src/derive.rs -+++ b/third_party/rust/syn/src/derive.rs -@@ -1,15 +1,15 @@ - use super::*; - use crate::punctuated::Punctuated; - - ast_struct! { - /// Data structure sent to a `proc_macro_derive` macro. - /// -- /// *This type is available if Syn is built with the `"derive"` feature.* -+ /// *This type is available only if Syn is built with the `"derive"` feature.* - pub struct DeriveInput { - /// Attributes tagged on the whole struct or enum. - pub attrs: Vec, - - /// Visibility of the struct or enum. - pub vis: Visibility, - - /// Name of the struct or enum. -@@ -21,17 +21,17 @@ ast_struct! { - /// Data within the struct or enum. - pub data: Data, - } - } - - ast_enum_of_structs! { - /// The storage of a struct, enum or union data structure. - /// -- /// *This type is available if Syn is built with the `"derive"` feature.* -+ /// *This type is available only if Syn is built with the `"derive"` feature.* - /// - /// # Syntax tree enum - /// - /// This type is a [syntax tree enum]. - /// - /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums - // - // TODO: change syntax-tree-enum link to an intra rustdoc link, currently -@@ -48,41 +48,41 @@ ast_enum_of_structs! { - } - - do_not_generate_to_tokens - } - - ast_struct! { - /// A struct input to a `proc_macro_derive` macro. - /// -- /// *This type is available if Syn is built with the `"derive"` -+ /// *This type is available only if Syn is built with the `"derive"` - /// feature.* - pub struct DataStruct { - pub struct_token: Token![struct], - pub fields: Fields, - pub semi_token: Option, - } - } - - ast_struct! { - /// An enum input to a `proc_macro_derive` macro. - /// -- /// *This type is available if Syn is built with the `"derive"` -+ /// *This type is available only if Syn is built with the `"derive"` - /// feature.* - pub struct DataEnum { - pub enum_token: Token![enum], - pub brace_token: token::Brace, - pub variants: Punctuated, - } - } - - ast_struct! { - /// An untagged union input to a `proc_macro_derive` macro. - /// -- /// *This type is available if Syn is built with the `"derive"` -+ /// *This type is available only if Syn is built with the `"derive"` - /// feature.* - pub struct DataUnion { - pub union_token: Token![union], - pub fields: FieldsNamed, - } - } - - #[cfg(feature = "parsing")] -diff --git a/third_party/rust/syn/src/discouraged.rs b/third_party/rust/syn/src/discouraged.rs ---- a/third_party/rust/syn/src/discouraged.rs -+++ b/third_party/rust/syn/src/discouraged.rs -@@ -11,17 +11,17 @@ pub trait Speculative { - /// stream to the fork to "commit" the parsing from the fork to the main - /// stream. - /// - /// If you can avoid doing this, you should, as it limits the ability to - /// generate useful errors. That said, it is often the only way to parse - /// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem - /// is that when the fork fails to parse an `A`, it's impossible to tell - /// whether that was because of a syntax error and the user meant to provide -- /// an `A`, or that the `A`s are finished and its time to start parsing -+ /// an `A`, or that the `A`s are finished and it's time to start parsing - /// `B`s. Use with care. - /// - /// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by - /// parsing `B*` and removing the leading members of `A` from the - /// repetition, bypassing the need to involve the downsides associated with - /// speculative parsing. - /// - /// [`ParseStream::fork`]: ParseBuffer::fork -@@ -67,17 +67,16 @@ pub trait Speculative { - /// # } - /// - /// impl Parse for PathSegment { - /// fn parse(input: ParseStream) -> Result { - /// if input.peek(Token![super]) - /// || input.peek(Token![self]) - /// || input.peek(Token![Self]) - /// || input.peek(Token![crate]) -- /// || input.peek(Token![extern]) - /// { - /// let ident = input.call(Ident::parse_any)?; - /// return Ok(PathSegment::from(ident)); - /// } - /// - /// let ident = input.parse()?; - /// if input.peek(Token![::]) && input.peek3(Token![<]) { - /// return Ok(PathSegment { -@@ -159,13 +158,37 @@ pub trait Speculative { - } - - impl<'a> Speculative for ParseBuffer<'a> { - fn advance_to(&self, fork: &Self) { - if !crate::buffer::same_scope(self.cursor(), fork.cursor()) { - panic!("Fork was not derived from the advancing parse stream"); - } - -+ let (self_unexp, self_sp) = inner_unexpected(self); -+ let (fork_unexp, fork_sp) = inner_unexpected(fork); -+ if !Rc::ptr_eq(&self_unexp, &fork_unexp) { -+ match (fork_sp, self_sp) { -+ // Unexpected set on the fork, but not on `self`, copy it over. -+ (Some(span), None) => { -+ self_unexp.set(Unexpected::Some(span)); -+ } -+ // Unexpected unset. Use chain to propagate errors from fork. -+ (None, None) => { -+ fork_unexp.set(Unexpected::Chain(self_unexp)); -+ -+ // Ensure toplevel 'unexpected' tokens from the fork don't -+ // bubble up the chain by replacing the root `unexpected` -+ // pointer, only 'unexpected' tokens from existing group -+ // parsers should bubble. -+ fork.unexpected -+ .set(Some(Rc::new(Cell::new(Unexpected::None)))); -+ } -+ // Unexpected has been set on `self`. No changes needed. -+ (_, Some(_)) => {} -+ } -+ } -+ - // See comment on `cell` in the struct definition. - self.cell - .set(unsafe { mem::transmute::>(fork.cursor()) }) - } - } -diff --git a/third_party/rust/syn/src/error.rs b/third_party/rust/syn/src/error.rs ---- a/third_party/rust/syn/src/error.rs -+++ b/third_party/rust/syn/src/error.rs -@@ -1,9 +1,8 @@ --use std; - use std::fmt::{self, Debug, Display}; - use std::iter::FromIterator; - use std::slice; - use std::vec; - - use proc_macro2::{ - Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, - }; -@@ -27,18 +26,18 @@ pub type Result = std::result::Result - /// message than simply panicking the macro. - /// - /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html - /// - /// When parsing macro input, the [`parse_macro_input!`] macro handles the - /// conversion to `compile_error!` automatically. - /// - /// ``` --/// extern crate proc_macro; --/// -+/// # extern crate proc_macro; -+/// # - /// use proc_macro::TokenStream; - /// use syn::{parse_macro_input, AttributeArgs, ItemFn}; - /// - /// # const IGNORE: &str = stringify! { - /// #[proc_macro_attribute] - /// # }; - /// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream { - /// let args = parse_macro_input!(args as AttributeArgs); -@@ -77,17 +76,16 @@ pub type Result = std::result::Result - /// # use proc_macro2::TokenStream; - /// # use syn::{DeriveInput, Result}; - /// # - /// # pub fn my_derive(input: DeriveInput) -> Result { - /// # unimplemented!() - /// # } - /// # } - /// ``` --#[derive(Clone)] - pub struct Error { - messages: Vec, - } - - struct ErrorMessage { - // Span is implemented as an index into a thread-local interner to keep the - // size small. It is not safe to access from a different thread. We want - // errors to be Send and Sync to play nicely with the Failure crate, so pin -@@ -245,16 +243,27 @@ pub fn new_at(scope: Span, c - if cursor.eof() { - Error::new(scope, format!("unexpected end of input, {}", message)) - } else { - let span = crate::buffer::open_span_of_group(cursor); - Error::new(span, message) - } - } - -+#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))] -+pub fn new2(start: Span, end: Span, message: T) -> Error { -+ Error { -+ messages: vec![ErrorMessage { -+ start_span: ThreadBound::new(start), -+ end_span: ThreadBound::new(end), -+ message: message.to_string(), -+ }], -+ } -+} -+ - impl Debug for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - if self.messages.len() == 1 { - formatter - .debug_tuple("Error") - .field(&self.messages[0]) - .finish() - } else { -@@ -273,16 +282,24 @@ impl Debug for ErrorMessage { - } - - impl Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(&self.messages[0].message) - } - } - -+impl Clone for Error { -+ fn clone(&self) -> Self { -+ Error { -+ messages: self.messages.clone(), -+ } -+ } -+} -+ - impl Clone for ErrorMessage { - fn clone(&self) -> Self { - let start = self - .start_span - .get() - .cloned() - .unwrap_or_else(Span::call_site); - let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site); -@@ -350,8 +367,16 @@ impl<'a> Iterator for Iter<'a> { - type Item = Error; - - fn next(&mut self) -> Option { - Some(Error { - messages: vec![self.messages.next()?.clone()], - }) - } - } -+ -+impl Extend for Error { -+ fn extend>(&mut self, iter: T) { -+ for err in iter { -+ self.combine(err); -+ } -+ } -+} -diff --git a/third_party/rust/syn/src/expr.rs b/third_party/rust/syn/src/expr.rs ---- a/third_party/rust/syn/src/expr.rs -+++ b/third_party/rust/syn/src/expr.rs -@@ -1,23 +1,26 @@ - use super::*; - use crate::punctuated::Punctuated; --#[cfg(feature = "extra-traits")] --use crate::tt::TokenStreamHelper; -+#[cfg(feature = "full")] -+use crate::reserved::Reserved; - use proc_macro2::{Span, TokenStream}; --#[cfg(feature = "extra-traits")] -+#[cfg(feature = "printing")] -+use quote::IdentFragment; -+#[cfg(feature = "printing")] -+use std::fmt::{self, Display}; - use std::hash::{Hash, Hasher}; --#[cfg(all(feature = "parsing", feature = "full"))] -+#[cfg(feature = "parsing")] - use std::mem; - - ast_enum_of_structs! { - /// A Rust expression. - /// -- /// *This type is available if Syn is built with the `"derive"` or `"full"` -- /// feature.* -+ /// *This type is available only if Syn is built with the `"derive"` or `"full"` -+ /// feature, but most of the variants are not available unless "full" is enabled.* - /// - /// # Syntax tree enums - /// - /// This type is a syntax tree enum. In Syn this and other syntax tree enums - /// are designed to be traversed using the following rebinding idiom. - /// - /// ``` - /// # use syn::Expr; -@@ -78,17 +81,17 @@ ast_enum_of_structs! { - /// if let Expr::Tuple(base) = *discriminant.base { - /// # } - /// # } - /// ``` - /// - /// A sign that you may not be choosing the right variable names is if you - /// see names getting repeated in your code, like accessing - /// `receiver.receiver` or `pat.pat` or `cond.cond`. -- pub enum Expr #manual_extra_traits { -+ pub enum Expr { - /// A slice literal expression: `[a, b, c, d]`. - Array(ExprArray), - - /// An assignment expression: `a = compute()`. - Assign(ExprAssign), - - /// A compound assignment expression: `counter += 1`. - AssignOp(ExprAssignOp), -@@ -223,191 +226,191 @@ ast_enum_of_structs! { - #[doc(hidden)] - __Nonexhaustive, - } - } - - ast_struct! { - /// A slice literal expression: `[a, b, c, d]`. - /// -- /// *This type is available if Syn is built with the `"full"` feature.* -+ /// *This type is available only if Syn is built with the `"full"` feature.* - pub struct ExprArray #full { - pub attrs: Vec, - pub bracket_token: token::Bracket, - pub elems: Punctuated, - } - } - - ast_struct! { - /// An assignment expression: `a = compute()`. - /// -- /// *This type is available if Syn is built with the `"full"` feature.* -+ /// *This type is available only if Syn is built with the `"full"` feature.* - pub struct ExprAssign #full { - pub attrs: Vec, - pub left: Box, - pub eq_token: Token![=], - pub right: Box, - } - } - - ast_struct! { - /// A compound assignment expression: `counter += 1`. - /// -- /// *This type is available if Syn is built with the `"full"` feature.* -+ /// *This type is available only if Syn is built with the `"full"` feature.* - pub struct ExprAssignOp #full { - pub attrs: Vec, - pub left: Box, - pub op: BinOp, - pub right: Box, - } - } - - ast_struct! { - /// An async block: `async { ... }`. - /// -- /// *This type is available if Syn is built with the `"full"` feature.* -+ /// *This type is available only if Syn is built with the `"full"` feature.* - pub struct ExprAsync #full { - pub attrs: Vec, - pub async_token: Token![async], - pub capture: Option, - pub block: Block, - } - } - - ast_struct! { - /// An await expression: `fut.await`. - /// -- /// *This type is available if Syn is built with the `"full"` feature.* -+ /// *This type is available only if Syn is built with the `"full"` feature.* - pub struct ExprAwait #full { - pub attrs: Vec, - pub base: Box, - pub dot_token: Token![.], - pub await_token: token::Await, - } - } - - ast_struct! { - /// A binary operation: `a + b`, `a * b`. - /// -- /// *This type is available if Syn is built with the `"derive"` or -+ /// *This type is available only if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct ExprBinary { - pub attrs: Vec, - pub left: Box, - pub op: BinOp, - pub right: Box, - } - } - - ast_struct! { - /// A blocked scope: `{ ... }`. - /// -- /// *This type is available if Syn is built with the `"full"` feature.* -+ /// *This type is available only if Syn is built with the `"full"` feature.* - pub struct ExprBlock #full { - pub attrs: Vec, - pub label: Option