red fixes (#468)

* red fixes

* remove magic number

@@ -48,6 +48,10 @@ string LogHandler::stderrToFile(const string &pathPrefix) {
   string current_time(buffer);
   string stderrFilename = pathPrefix + "_stderr_" + current_time;
   FILE *stderr_stream = freopen(stderrFilename.c_str(), "w", stderr);
+  fs::permissions(
+      stderrFilename,
+      fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read,
+      fs::perm_options::replace);
   if (!stderr_stream) {
     STFATAL << "Invalid filename " << stderrFilename;
   }


Fixing BadMessageCallback usage by SessionStorage

TBR: jam@chromium.org
Bug: 916523
Change-Id: I027cc818cfba917906844ad2ec0edd7fa4761bd1
Reviewed-on: https://chromium-review.googlesource.com/c/1401604
Commit-Queue: Daniel Murphy <dmurph@chromium.org>
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
Reviewed-by: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#621772}

@@ -48,12 +48,19 @@ class CONTENT_EXPORT DOMStorageContextWrapper
       public base::RefCountedThreadSafe<DOMStorageContextWrapper> {
  public:
   // If |data_path| is empty, nothing will be saved to disk.
-  DOMStorageContextWrapper(
+  static scoped_refptr<DOMStorageContextWrapper> Create(
       service_manager::Connector* connector,
-      const base::FilePath& data_path,
+      const base::FilePath& profile_path,
       const base::FilePath& local_partition_path,
       storage::SpecialStoragePolicy* special_storage_policy);

+  DOMStorageContextWrapper(
+      base::FilePath legacy_local_storage_path,
+      scoped_refptr<DOMStorageContextImpl> context_impl,
+      scoped_refptr<base::SequencedTaskRunner> mojo_task_runner,
+      LocalStorageContextMojo* mojo_local_storage_context,
+      SessionStorageContextMojo* mojo_session_storage_context);
+
   // DOMStorageContext implementation.
   void GetLocalStorageUsage(GetLocalStorageUsageCallback callback) override;
   void GetSessionStorageUsage(GetSessionStorageUsageCallback callback) override;


additional checks in parseSonySRF

parseSonySR2: buffer size check

@@ -1799,6 +1799,14 @@ void LibRaw::parseSonySR2(uchar *cbuf_SR2, unsigned SR2SubIFDOffset,
   float num;
   int i;
   int WBCTC_count;
+#define CHECKBUFFER_N(offset,N)                                     \
+  do                                                                \
+  {                                                                 \
+    if ((((offset) + (N)) > SR2SubIFDLength) || ((offset) < 0))     \
+      return;														\
+  } while (0)
+
+  CHECKBUFFER_N(0, 2);
   entries = sget2(cbuf_SR2);
   if (entries > 1000)
     return;
@@ -1812,43 +1820,52 @@ void LibRaw::parseSonySR2(uchar *cbuf_SR2, unsigned SR2SubIFDOffset,
       if (dng_writer == nonDNG) {
         switch (tag_id) {
         case 0x7300:
-          FORC4 cblack[c] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 4,0);
+			FORC4 cblack[c] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
           TagProcessed = 1;
           break;
         case 0x7303:
-          FORC4 cam_mul[GRBG_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 4, 0);
+			FORC4 cam_mul[GRBG_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
           TagProcessed = 1;
           break;
         case 0x7310:
-          FORC4 cblack[RGGB_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 4, 0);
+			FORC4 cblack[RGGB_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
           i = cblack[3];
           FORC3 if (i > cblack[c]) i = cblack[c];
           FORC4 cblack[c] -= i;
           black = i;
           TagProcessed = 1;
           break;
         case 0x7313:
-          FORC4 cam_mul[RGGB_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 4, 0);
+			FORC4 cam_mul[RGGB_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
           TagProcessed = 1;
           break;
         case 0x74a0:
-          ilm.MaxAp4MaxFocal = sgetreal(tag_type, cbuf_SR2 + tag_dataoffset);
+			CHECKBUFFER_N(tag_dataoffset, 4);
+			ilm.MaxAp4MaxFocal = sgetreal(tag_type, cbuf_SR2 + tag_dataoffset);
           TagProcessed = 1;
           break;
         case 0x74a1:
-          ilm.MaxAp4MinFocal = sgetreal(tag_type, cbuf_SR2 + tag_dataoffset);
+			CHECKBUFFER_N(tag_dataoffset, 4);
+			ilm.MaxAp4MinFocal = sgetreal(tag_type, cbuf_SR2 + tag_dataoffset);
           TagProcessed = 1;
           break;
         case 0x74a2:
-          ilm.MaxFocal = sgetreal(tag_type, cbuf_SR2 + tag_dataoffset);
+			CHECKBUFFER_N(tag_dataoffset, 4);
+			ilm.MaxFocal = sgetreal(tag_type, cbuf_SR2 + tag_dataoffset);
           TagProcessed = 1;
           break;
         case 0x74a3:
-          ilm.MinFocal = sgetreal(tag_type, cbuf_SR2 + tag_dataoffset);
+			CHECKBUFFER_N(tag_dataoffset, 4);
+			ilm.MinFocal = sgetreal(tag_type, cbuf_SR2 + tag_dataoffset);
           TagProcessed = 1;
           break;
         case 0x7800:
-          for (i = 0; i < 3; i++)
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 8, 2);
+		  for (i = 0; i < 3; i++)
           {
             num = 0.0;
             for (c = 0; c < 3; c++)
@@ -1865,12 +1882,14 @@ void LibRaw::parseSonySR2(uchar *cbuf_SR2, unsigned SR2SubIFDOffset,
         case 0x787f:
           if (tag_datalen == 3)
           {
-            FORC3 imgdata.color.linear_max[c] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			  CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 2, 2);
+			  FORC3 imgdata.color.linear_max[c] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
             imgdata.color.linear_max[3] = imgdata.color.linear_max[1];
           }
           else if (tag_datalen == 1)
           {
-            imgdata.color.linear_max[0] = imgdata.color.linear_max[1] =
+			  CHECKBUFFER_N(tag_dataoffset, 2);
+			  imgdata.color.linear_max[0] = imgdata.color.linear_max[1] =
                 imgdata.color.linear_max[2] = imgdata.color.linear_max[3] =
                     sget2(cbuf_SR2 + tag_dataoffset);
           }
@@ -1884,37 +1903,44 @@ void LibRaw::parseSonySR2(uchar *cbuf_SR2, unsigned SR2SubIFDOffset,
           i = tag_id - 0x7480;
           if (Sony_SR2_wb_list[i] > 255) {
             icWBCCTC[WBCTC_count][0] = Sony_SR2_wb_list[i];
-            FORC3 icWBCCTC[WBCTC_count][c + 1] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 2, 2);
+			FORC3 icWBCCTC[WBCTC_count][c + 1] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
             icWBCCTC[WBCTC_count][4] = icWBCCTC[WBCTC_count][2];
             WBCTC_count++;
           } else {
-            FORC3 icWBC[Sony_SR2_wb_list[i]][c] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			  CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 2, 2);
+			  FORC3 icWBC[Sony_SR2_wb_list[i]][c] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
             icWBC[Sony_SR2_wb_list[i]][3] = icWBC[Sony_SR2_wb_list[i]][1];
           }
         } else if ((tag_id >= 0x7820) && (tag_id <= 0x782d)) {
           i = tag_id - 0x7820;
           if (Sony_SR2_wb_list1[i] > 255) {
             icWBCCTC[WBCTC_count][0] = Sony_SR2_wb_list1[i];
-            FORC3 icWBCCTC[WBCTC_count][c + 1] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 2, 2);
+			FORC3 icWBCCTC[WBCTC_count][c + 1] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
             icWBCCTC[WBCTC_count][4] = icWBCCTC[WBCTC_count][2];
             if (Sony_SR2_wb_list1[i] == 3200) {
               FORC3 icWBC[LIBRAW_WBI_StudioTungsten][c] = icWBCCTC[WBCTC_count][c + 1];
               icWBC[LIBRAW_WBI_StudioTungsten][3] = icWBC[LIBRAW_WBI_StudioTungsten][1];
             }
             WBCTC_count++;
           } else {
-            FORC3 icWBC[Sony_SR2_wb_list1[i]][c] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			  CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 2, 2);
+			  FORC3 icWBC[Sony_SR2_wb_list1[i]][c] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
             icWBC[Sony_SR2_wb_list1[i]][3] = icWBC[Sony_SR2_wb_list1[i]][1];
           }
         } else if (tag_id == 0x7302) {
-          FORC4 icWBC[LIBRAW_WBI_Auto][GRBG_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 3, 2);
+			FORC4 icWBC[LIBRAW_WBI_Auto][GRBG_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
         } else if (tag_id == 0x7312) {
-          FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
+			CHECKBUFFER_N(tag_dataoffset + tag_dataunitlen * 3, 2);
+			FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = sget2(cbuf_SR2 + tag_dataoffset + tag_dataunitlen * c);
         }
       }
     }
   }
 }
+#undef CHECKBUFFER_N

 void LibRaw::parseSonySRF(unsigned len)
 {
@@ -1935,10 +1961,10 @@ void LibRaw::parseSonySRF(unsigned len)
   INT64 srf_offset, tag_offset, tag_data, tag_dataoffset;
   int tag_dataunitlen;
   uchar *srf_buf;
-  short entries;
+  ushort entries;
   unsigned tag_id, tag_type, tag_datalen;

-  srf_buf = (uchar *)malloc(len);
+  srf_buf = (uchar *)malloc(len+64);
   fread(srf_buf, len, 1, ifp);

   offset += srf_buf[offset] << 2;
@@ -1995,9 +2021,11 @@ void LibRaw::parseSonySRF(unsigned len)
                    &tag_offset, &tag_id, &tag_type, &tag_dataoffset,
                    &tag_datalen, &tag_dataunitlen) == 0) {
       if (tag_id == 0x0000) {
-        SRF2Key = sget4(srf_buf + tag_dataoffset);
+		  CHECKBUFFER_SGET4(tag_dataoffset);
+		  SRF2Key = sget4(srf_buf + tag_dataoffset);
       } else if (tag_id == 0x0001) {
-        RawDataKey = sget4(srf_buf + tag_dataoffset);
+		  CHECKBUFFER_SGET4(tag_dataoffset);
+		  RawDataKey = sget4(srf_buf + tag_dataoffset);
       }
     } else goto restore_after_parseSonySRF;
   }
@@ -2019,20 +2047,22 @@ void LibRaw::parseSonySRF(unsigned len)
   tag_offset = offset;

   while (entries--) {
-    if (tiff_sget (save, srf_buf, len,
+	  if (tiff_sget(save, srf_buf, len,
                    &tag_offset, &tag_id, &tag_type, &tag_dataoffset,
                    &tag_datalen, &tag_dataunitlen) == 0) {
       if ((tag_id >= 0x00c0) && (tag_id <= 0x00ce)) {
         i = (tag_id - 0x00c0) % 3;
         nWB = (tag_id - 0x00c0) / 3;
-        icWBC[Sony_SRF_wb_list[nWB]][i] = sget4(srf_buf + tag_dataoffset);
+		CHECKBUFFER_SGET4(tag_dataoffset);
+		icWBC[Sony_SRF_wb_list[nWB]][i] = sget4(srf_buf + tag_dataoffset);
         if (i == 1) {
           icWBC[Sony_SRF_wb_list[nWB]][3] =
             icWBC[Sony_SRF_wb_list[nWB]][i];
         }
       } else if ((tag_id >= 0x00d0) && (tag_id <= 0x00d2)) {
         i = (tag_id - 0x00d0) % 3;
-        cam_mul[i] = sget4(srf_buf + tag_dataoffset);
+		CHECKBUFFER_SGET4(tag_dataoffset);
+		cam_mul[i] = sget4(srf_buf + tag_dataoffset);
         if (i == 1) {
           cam_mul[3] = cam_mul[i];
         }
@@ -2044,16 +2074,20 @@ void LibRaw::parseSonySRF(unsigned len)
         0x0005  RawDataLength
         */
       case 0x0043:
-        ilm.MaxAp4MaxFocal = sgetreal(tag_type, srf_buf + tag_dataoffset);
+		  CHECKBUFFER_SGET4(tag_dataoffset); // need to add extra space
+		  ilm.MaxAp4MaxFocal = sgetreal(tag_type, srf_buf + tag_dataoffset);
         break;
       case 0x0044:
-         ilm.MaxAp4MinFocal = sgetreal(tag_type, srf_buf + tag_dataoffset);
+		  CHECKBUFFER_SGET4(tag_dataoffset);
+		  ilm.MaxAp4MinFocal = sgetreal(tag_type, srf_buf + tag_dataoffset);
         break;
       case 0x0045:
-        ilm.MinFocal = sgetreal(tag_type, srf_buf + tag_dataoffset);
+		  CHECKBUFFER_SGET4(tag_dataoffset);
+		  ilm.MinFocal = sgetreal(tag_type, srf_buf + tag_dataoffset);
         break;
       case 0x0046:
-        ilm.MaxFocal = sgetreal(tag_type, srf_buf + tag_dataoffset);
+		  CHECKBUFFER_SGET4(tag_dataoffset);
+		  ilm.MaxFocal = sgetreal(tag_type, srf_buf + tag_dataoffset);
         break;
       }
     } else goto restore_after_parseSonySRF;


Re-sync with internal repository (#822)

Co-authored-by: Facebook Community Bot <6422482+facebook-github-bot@users.noreply.github.com>

@@ -236,8 +236,11 @@ BCProviderFromSrc::createBCProviderFromSrcImpl(
   opts.staticBuiltinsEnabled =
       context->getOptimizationSettings().staticBuiltins;
   opts.verifyIR = compileFlags.verifyIR;
-  auto bytecode = createBCProviderFromSrc(
-      hbc::generateBytecodeModule(&M, M.getTopLevelFunction(), opts));
+  auto BM = hbc::generateBytecodeModule(&M, M.getTopLevelFunction(), opts);
+  if (context->getSourceErrorManager().getErrorCount() > 0) {
+    return {nullptr, getErrorString()};
+  }
+  auto bytecode = createBCProviderFromSrc(std::move(BM));
   bytecode->singleFunction_ = isSingleFunctionExpression(parsed.getValue());
   return {std::move(bytecode), std::string{}};
 }


Re-sync with internal repository (#772)

Co-authored-by: Facebook Community Bot <6422482+facebook-github-bot@users.noreply.github.com>

@@ -238,12 +238,16 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
 // Define this out-of-line to dissuade the C++ compiler from inlining it.
 template <typename T, bool isPodLike>
 void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
-  if (MinSize > UINT32_MAX)
-    report_bad_alloc_error("SmallVector capacity overflow during allocation");
-
   // Always grow, even from zero.
-  size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2));
-  NewCapacity = std::min(std::max(NewCapacity, MinSize), size_t(UINT32_MAX));
+  constexpr size_t MinGrowth = 2;
+  size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + MinGrowth));
+  NewCapacity = static_cast<unsigned>(std::max(NewCapacity, MinSize));
+  // Ensure that NewCapacity did not overflow an unsigned int,
+  // and that the capacity in bytes will not overflow a size_t.
+  if (NewCapacity <= this->capacity() ||
+      NewCapacity < MinSize ||
+      NewCapacity > size_t(-1) / sizeof(T))
+    report_bad_alloc_error("SmallVector capacity overflow during allocation");
   T *NewElts = static_cast<T*>(llvh::safe_malloc(NewCapacity*sizeof(T)));

   // Move the elements over.


Issue: 15232 AllowScript should use atom::ContentSettingsManager like other Allow* methods in the observer

@@ -432,11 +432,13 @@ bool ContentSettingsObserver::AllowScript(bool enabled_per_settings) {
   // IsWhitelistedForContentSettings(); if there is only the default rule
   // allowing all scripts, it's quicker this way.
   bool allow = true;
-  if (content_setting_rules_) {
-    ContentSetting setting = GetContentSettingFromRules(
-        content_setting_rules_->script_rules, frame,
-        url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL());
-    allow = setting != CONTENT_SETTING_BLOCK;
+  if (content_settings_manager_->content_settings()) {
+    allow =
+        content_settings_manager_->GetSetting(
+          ContentSettingsManager::GetOriginOrURL(render_frame()->GetWebFrame()),
+          url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL(),
+          "javascript",
+          allow) != CONTENT_SETTING_BLOCK;
   }
   allow = allow || IsWhitelistedForContentSettings();


sending an invite with a request-uri longer than 255 characters can cause a crash (#238)

@@ -529,7 +529,9 @@ namespace drachtio {
              }

             //prevent looping messages
-            normalizeSipUri( requestUri, 0 ) ;
+            if (!normalizeSipUri( requestUri, 0 )) {
+                throw std::runtime_error(string("invalid request-uri: ") + requestUri ) ;
+            }
             if( isLocalSipUri( requestUri ) ) {
                 throw std::runtime_error("can not send request to myself") ;
             }


Avoid HashDoS attacks via random per-session hash initial state (#1433)

@@ -130,7 +130,9 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
         removeHeaderBy(key);
     }

-    const std::unordered_map<std::string, std::string> &headers() const override
+    const std::
+        unordered_map<std::string, std::string, utils::internal::SafeStringHash>
+            &headers() const override
     {
         return headers_;
     }
@@ -200,7 +202,9 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
         return defaultCookie;
     }

-    const std::unordered_map<std::string, Cookie> &cookies() const override
+    const std::
+        unordered_map<std::string, Cookie, utils::internal::SafeStringHash>
+            &cookies() const override
     {
         return cookies_;
     }
@@ -446,8 +450,11 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
         statusMessage_ = string_view{message, messageLength};
     }

-    std::unordered_map<std::string, std::string> headers_;
-    std::unordered_map<std::string, Cookie> cookies_;
+    std::
+        unordered_map<std::string, std::string, utils::internal::SafeStringHash>
+            headers_;
+    std::unordered_map<std::string, Cookie, utils::internal::SafeStringHash>
+        cookies_;

     int customStatusCode_{-1};
     HttpStatusCode statusCode_{kUnknown};


Merge pull request #190 from japroc/fix-potential-sqli-through-fs-path

Fix potential sql injection through fs path

@@ -214,6 +214,9 @@ DSCIOManager::dsc_import_input_from_source() {

     string node = bfs::initial_path().filename().generic_string();
     string server = bfs::initial_path().parent_path().filename().generic_string();
+    //fix potential sql injection
+    replace(node.begin(), node.end(), '\'', '_');
+    replace(server.begin(), server.end(), '\'', '_');
     //transform to 'internal' name
     replace(server.begin(), server.end(), '-', '_');
     replace_string(server, ".", "__");


Bug 1742421 - Part 3: [widget/windows] Exit fullscreen when changing sizemode; r=mhowell,edgar

Differential Revision: https://phabricator.services.mozilla.com/D135606

@@ -2294,57 +2294,107 @@ static UINT GetCurrentShowCmd(HWND aWnd) {
   return pl.showCmd;
 }

-// Maximize, minimize or restore the window.
-void nsWindow::SetSizeMode(nsSizeMode aMode) {
+void nsWindow::SetSizeModeInternal(nsSizeMode aMode, nsIScreen* aFullscreenTarget) {
   // Let's not try and do anything if we're already in that state.
   // (This is needed to prevent problems when calling window.minimize(), which
   // calls us directly, and then the OS triggers another call to us.)
   if (aMode == mSizeMode) return;

-  // If we are still displaying a maximized pre-XUL skeleton UI, ignore the
-  // noise of sizemode changes. Once we have "shown" the window for the first
-  // time (called nsWindow::Show(true), even though the window is already
-  // technically displayed), we will again accept sizemode changes.
-  if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
-    return;
+  const bool currentlyFullscreen = mSizeMode == nsSizeMode_Fullscreen;
+  const bool requestedFullscreen = aMode == nsSizeMode_Fullscreen;
+  const bool fullscreenChanging = currentlyFullscreen || requestedFullscreen;
+
+  MOZ_DIAGNOSTIC_ASSERT(currentlyFullscreen == mFullscreenMode);
+
+  if (fullscreenChanging) {
+    if (mWidgetListener) {
+      mWidgetListener->FullscreenWillChange(requestedFullscreen);
+    }
+
+    mFullscreenMode = requestedFullscreen;
   }

   // save the requested state
   mLastSizeMode = mSizeMode;
   nsBaseWidget::SetSizeMode(aMode);
-  if (mIsVisible) {
-    int mode;

+  if (mIsVisible) {
     switch (aMode) {
       case nsSizeMode_Fullscreen:
-        mode = SW_SHOW;
+        ::ShowWindow(mWnd, SW_SHOW);
         break;

       case nsSizeMode_Maximized:
-        mode = SW_MAXIMIZE;
+        ::ShowWindow(mWnd, SW_MAXIMIZE);
         break;

       case nsSizeMode_Minimized:
-        mode = SW_MINIMIZE;
+        ::ShowWindow(mWnd, SW_MINIMIZE);
         break;

       default:
-        mode = SW_RESTORE;
+        MOZ_ASSERT(aMode == nsSizeMode_Normal);
+
+        // Don't call ::ShowWindow if we're trying to "restore" a window that is
+        // already in a normal state.  Prevents a bug where snapping to one side
+        // of the screen and then minimizing would cause Windows to forget our
+        // window's correct restored position/size.
+        if (GetCurrentShowCmd(mWnd) != SW_SHOWNORMAL) {
+          ::ShowWindow(mWnd, SW_RESTORE);
+        }
     }
+  }

-    // Don't call ::ShowWindow if we're trying to "restore" a window that is
-    // already in a normal state.  Prevents a bug where snapping to one side
-    // of the screen and then minimizing would cause Windows to forget our
-    // window's correct restored position/size.
-    if (!(GetCurrentShowCmd(mWnd) == SW_SHOWNORMAL && mode == SW_RESTORE)) {
-      ::ShowWindow(mWnd, mode);
+  if (fullscreenChanging) {
+    // taskbarInfo will be nullptr pre Windows 7 until Bug 680227 is resolved.
+    nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);
+
+    if (requestedFullscreen && taskbarInfo) {
+      // Notify the taskbar that we will be entering full screen mode.
+      taskbarInfo->PrepareFullScreenHWND(mWnd, TRUE);
     }
-    // we activate here to ensure that the right child window is focused
-    if (mode == SW_MAXIMIZE || mode == SW_SHOW)
+
+    // If we are going fullscreen, the window size continues to change
+    // and the window will be reflow again then.
+    UpdateNonClientMargins(mSizeMode, /* Reflow */ !requestedFullscreen);
+
+    // Will call hide chrome, reposition window. Note this will
+    // also cache dimensions for restoration, so it should only
+    // be called once per fullscreen request.
+    nsBaseWidget::InfallibleMakeFullScreen(requestedFullscreen, aFullscreenTarget);
+
+    if (mIsVisible && aMode != nsSizeMode_Minimized) {
       DispatchFocusToTopLevelWindow(true);
+    }
+
+    if (!requestedFullscreen && taskbarInfo) {
+      // Notify the taskbar that we have exited full screen mode.
+      taskbarInfo->PrepareFullScreenHWND(mWnd, FALSE);
+    }
+
+    OnSizeModeChange(mSizeMode);
+
+    if (mWidgetListener) {
+      mWidgetListener->FullscreenChanged(requestedFullscreen);
+    }
+  } else if(mIsVisible && aMode != nsSizeMode_Minimized) {
+    DispatchFocusToTopLevelWindow(true);
   }
 }

+// Maximize, minimize or restore the window.
+void nsWindow::SetSizeMode(nsSizeMode aMode) {
+  // If we are still displaying a maximized pre-XUL skeleton UI, ignore the
+  // noise of sizemode changes. Once we have "shown" the window for the first
+  // time (called nsWindow::Show(true), even though the window is already
+  // technically displayed), we will again accept sizemode changes.
+  if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
+    return;
+  }
+
+  SetSizeModeInternal(aMode, nullptr);
+}
+
 void DoGetWorkspaceID(HWND aWnd, nsAString* aWorkspaceID) {
   RefPtr<IVirtualDesktopManager> desktopManager = gVirtualDesktopManager;
   if (!desktopManager || !aWnd) {
@@ -3667,51 +3717,11 @@ void nsWindow::CleanupFullscreenTransition() {
 }

 nsresult nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) {
-  // taskbarInfo will be nullptr pre Windows 7 until Bug 680227 is resolved.
-  nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);
-
-  if (mWidgetListener) {
-    mWidgetListener->FullscreenWillChange(aFullScreen);
-  }
-
-  mFullscreenMode = aFullScreen;
   if (aFullScreen) {
-    if (mSizeMode == nsSizeMode_Fullscreen) return NS_OK;
     mOldSizeMode = mSizeMode;
-    SetSizeMode(nsSizeMode_Fullscreen);
-
-    // Notify the taskbar that we will be entering full screen mode.
-    if (taskbarInfo) {
-      taskbarInfo->PrepareFullScreenHWND(mWnd, TRUE);
-    }
+    SetSizeModeInternal(nsSizeMode_Fullscreen, aTargetScreen);
   } else {
-    SetSizeMode(mOldSizeMode);
-  }
-
-  // If we are going fullscreen, the window size continues to change
-  // and the window will be reflow again then.
-  UpdateNonClientMargins(mSizeMode, /* Reflow */ !aFullScreen);
-
-  // Will call hide chrome, reposition window. Note this will
-  // also cache dimensions for restoration, so it should only
-  // be called once per fullscreen request.
-  nsBaseWidget::InfallibleMakeFullScreen(aFullScreen, aTargetScreen);
-
-  if (mIsVisible && !aFullScreen && mOldSizeMode == nsSizeMode_Normal) {
-    // Ensure the window exiting fullscreen get activated. Window
-    // activation might be bypassed in SetSizeMode.
-    DispatchFocusToTopLevelWindow(true);
-  }
-
-  // Notify the taskbar that we have exited full screen mode.
-  if (!aFullScreen && taskbarInfo) {
-    taskbarInfo->PrepareFullScreenHWND(mWnd, FALSE);
-  }
-
-  OnSizeModeChange(mSizeMode);
-
-  if (mWidgetListener) {
-    mWidgetListener->FullscreenChanged(aFullScreen);
+    SetSizeModeInternal(mOldSizeMode, aTargetScreen);
   }

   return NS_OK;


Bug 1736243 - Make SVGObserverUtils::GetAndObserveTextPathsPath not observe on continuations. r=longsonr

Differential Revision: https://phabricator.services.mozilla.com/D139485

@@ -1399,6 +1399,10 @@ SVGObserverUtils::ReferenceState SVGObserverUtils::GetAndObserveMasks(

 SVGGeometryElement* SVGObserverUtils::GetAndObserveTextPathsPath(
     nsIFrame* aTextPathFrame) {
+  // Continuations can come and go during reflow, and we don't need to observe
+  // the referenced element more than once for a given node.
+  aTextPathFrame = aTextPathFrame->FirstContinuation();
+
   SVGTextPathObserver* property =
       aTextPathFrame->GetProperty(HrefAsTextPathProperty());


invert_pt_dynamic: fix thinko; PackLinuxElf64help1 insist on ELF

https://github.com/upx/upx/issues/631
	modified:   src/p_lx_elf.cpp

@@ -256,7 +256,8 @@ PackLinuxElf32::PackLinuxElf32help1(InputFile *f)
     e_phnum = get_te16(&ehdri.e_phnum);
     e_shnum = get_te16(&ehdri.e_shnum);
     unsigned const e_phentsize = get_te16(&ehdri.e_phentsize);
-    if (ehdri.e_ident[Elf32_Ehdr::EI_CLASS]!=Elf32_Ehdr::ELFCLASS32
+    if (memcmp((char const *)&ehdri, "\x7f\x45\x4c\x46", 4)  // "\177ELF"
+    || ehdri.e_ident[Elf32_Ehdr::EI_CLASS]!=Elf32_Ehdr::ELFCLASS32
     || sizeof(Elf32_Phdr) != e_phentsize
     || (Elf32_Ehdr::ELFDATA2MSB == ehdri.e_ident[Elf32_Ehdr::EI_DATA]
             && &N_BELE_RTP::be_policy != bele)
@@ -761,7 +762,8 @@ PackLinuxElf64::PackLinuxElf64help1(InputFile *f)
     e_phnum = get_te16(&ehdri.e_phnum);
     e_shnum = get_te16(&ehdri.e_shnum);
     unsigned const e_phentsize = get_te16(&ehdri.e_phentsize);
-    if (ehdri.e_ident[Elf64_Ehdr::EI_CLASS]!=Elf64_Ehdr::ELFCLASS64
+    if (memcmp((char const *)&ehdri, "\x7f\x45\x4c\x46", 4)  // "\177ELF"
+    || ehdri.e_ident[Elf64_Ehdr::EI_CLASS]!=Elf64_Ehdr::ELFCLASS64
     || sizeof(Elf64_Phdr) != e_phentsize
     || (Elf64_Ehdr::ELFDATA2MSB == ehdri.e_ident[Elf64_Ehdr::EI_DATA]
             && &N_BELE_RTP::be_policy != bele)
@@ -5780,7 +5782,7 @@ PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp, upx_uint64_t headway)
         }
         if (file_size <= dt_offsets[n_off]) {
             char msg[60]; snprintf(msg, sizeof(msg), "bad DT_{%#x} = %#x (beyond EOF)",
-                dt_names[k], dt_offsets[n_off]);
+                k, dt_offsets[n_off]);
                 throwCantPack(msg);
         }
         n_off += !!dt_offsets[n_off];


shuffle selected coins before transaction finalization

@@ -2889,20 +2889,11 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
                     nChangePosInOut = -1;
                 }

-                // Fill vin
+                // Dummy fill vin for maximum size estimation
                 //
-                // Note how the sequence number is set to non-maxint so that
-                // the nLockTime set above actually works.
-                //
-                // BIP125 defines opt-in RBF as any nSequence < maxint-1, so
-                // we use the highest possible value in that range (maxint-2)
-                // to avoid conflicting with other possible uses of nSequence,
-                // and in the spirit of "smallest possible change from prior
-                // behavior."
-                const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
-                for (const auto& coin : setCoins)
-                    txNew.vin.push_back(CTxIn(coin.outpoint,CScript(),
-                                              nSequence));
+                for (const auto& coin : setCoins) {
+                    txNew.vin.push_back(CTxIn(coin.outpoint,CScript()));
+                }

                 nBytes = CalculateMaximumSignedTxSize(txNew, this);
                 if (nBytes < 0) {
@@ -2992,11 +2983,29 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac

         if (nChangePosInOut == -1) reservekey.ReturnKey(); // Return any reserved key if we don't have change

+        // Shuffle selected coins and fill in final vin
+        txNew.vin.clear();
+        std::vector<CInputCoin> selected_coins(setCoins.begin(), setCoins.end());
+        std::shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext());
+
+        // Note how the sequence number is set to non-maxint so that
+        // the nLockTime set above actually works.
+        //
+        // BIP125 defines opt-in RBF as any nSequence < maxint-1, so
+        // we use the highest possible value in that range (maxint-2)
+        // to avoid conflicting with other possible uses of nSequence,
+        // and in the spirit of "smallest possible change from prior
+        // behavior."
+        const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
+        for (const auto& coin : selected_coins) {
+            txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence));
+        }
+
         if (sign)
         {
             CTransaction txNewConst(txNew);
             int nIn = 0;
-            for (const auto& coin : setCoins)
+            for (const auto& coin : selected_coins)
             {
                 const CScript& scriptPubKey = coin.txout.scriptPubKey;
                 SignatureData sigdata;


revert most of d7a0084bf99d618d1dc26a54fd413db7ae8b8e63

See php-memcached-dev/php-memcached#531

@@ -761,7 +761,7 @@ static memcached_return_t _read_one_response(memcached_instance_st *instance, ch
     rc = textual_read_one_response(instance, buffer, buffer_length, result);
   }

-  if (memcached_fatal(rc) && rc != MEMCACHED_TIMEOUT) {
+  if (memcached_fatal(rc)) {
     memcached_io_reset(instance);
   }


Merge pull request #513 from protobuf-c/edmonds/issue499

Fix issue #499: unsigned integer overflow

@@ -2603,10 +2603,13 @@ parse_required_member(ScannedMember *scanned_member,
 			return FALSE;

 		def_mess = scanned_member->field->default_value;
-		subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
-						 allocator,
-						 len - pref_len,
-						 data + pref_len);
+		if (len >= pref_len)
+			subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
+							 allocator,
+							 len - pref_len,
+							 data + pref_len);
+		else
+			subm = NULL;

 		if (maybe_clear &&
 		    *pmessage != NULL &&


Re-sync with internal repository (#960)

Co-authored-by: Facebook Community Bot <6422482+facebook-github-bot@users.noreply.github.com>

@@ -60,6 +60,12 @@ class TypeInferenceImpl {
   bool runOnModule(Module *M);
 };

+/// \return if the given \p type is a BigInt|Object, which used to determine if
+/// unary/binary operations may have a BigInt result.
+static bool isBigIntOrObject(Type type) {
+  return type.canBeBigInt() || type.canBeObject();
+}
+
 static bool inferUnaryArith(UnaryOperatorInst *UOI, Type numberResultType) {
   Value *op = UOI->getSingleOperand();

@@ -73,10 +79,11 @@ static bool inferUnaryArith(UnaryOperatorInst *UOI, Type numberResultType) {
     return true;
   }

-  Type mayBeBigInt =
-      op->getType().canBeBigInt() ? Type::createBigInt() : Type::createNoType();
+  Type mayBeBigInt = isBigIntOrObject(op->getType()) ? Type::createBigInt()
+                                                     : Type::createNoType();

-  // - ?? => Number|?BigInt. BigInt is only possible if op.Type canBeBigInt.
+  // - ?? => Number|?BigInt. BigInt is only possible if op.Type is
+  // BigInt|Object.
   UOI->setType(Type::unionTy(numberResultType, mayBeBigInt));
   return true;
 }
@@ -298,12 +305,12 @@ static bool inferBinaryArith(
     return true;
   }

-  Type mayBeBigInt = LeftTy.canBeBigInt() && RightTy.canBeBigInt()
+  Type mayBeBigInt = (isBigIntOrObject(LeftTy) && isBigIntOrObject(RightTy))
       ? Type::createBigInt()
       : Type::createNoType();

-  // ?? - ?? => Number|?BigInt. BigInt is only possible if both operands can be
-  // BigInt due to the no automatic BigInt conversion.
+  // ?? - ?? => Number|?BigInt. BigInt is only possible if both operands are
+  // BigInt|Object due to the no automatic BigInt conversion.
   BOI->setType(Type::unionTy(numberType, mayBeBigInt));
   return true;
 }
@@ -312,12 +319,12 @@ static bool inferBinaryBitwise(BinaryOperatorInst *BOI) {
   Type LeftTy = BOI->getLeftHandSide()->getType();
   Type RightTy = BOI->getRightHandSide()->getType();

-  Type mayBeBigInt = LeftTy.canBeBigInt() && RightTy.canBeBigInt()
+  Type mayBeBigInt = (isBigIntOrObject(LeftTy) && isBigIntOrObject(RightTy))
       ? Type::createBigInt()
       : Type::createNoType();

-  // ?? - ?? => Int32|?BigInt. BigInt is only possible if both operands can be
-  // BigInt due to the no automatic BigInt conversion.
+  // ?? - ?? => Int32|?BigInt. BigInt is only possible if both operands are
+  // BigInt|Object due to the no automatic BigInt conversion.
   BOI->setType(Type::unionTy(Type::createInt32(), mayBeBigInt));
   return true;
 }
@@ -391,7 +398,7 @@ static bool inferBinaryInst(BinaryOperatorInst *BOI) {
       // ?BigInt + ?BigInt => ?BigInt. Both operands need to "may be a BigInt"
       // for a possible BigInt result from this operator. This is true because
       // there's no automative BigInt type conversion.
-      Type mayBeBigInt = (LeftTy.canBeBigInt() && RightTy.canBeBigInt())
+      Type mayBeBigInt = (isBigIntOrObject(LeftTy) && isBigIntOrObject(RightTy))
           ? Type::createBigInt()
           : Type::createNoType();


Re-sync with internal repository (#908)

Fixes for CVE-2023-23556, and CVE-2023-24833.

Co-authored-by: Facebook Community Bot <6422482+facebook-github-bot@users.noreply.github.com>

@@ -1093,10 +1093,6 @@ class StandardSortModel : public SortModel {
     JSObject::getComputedPrimitiveDescriptor(
         obj_, runtime_, aHandle_, aDescObjHandle_, aTmpNameStorage_, aDesc);

-    ComputedPropertyDescriptor bDesc;
-    JSObject::getComputedPrimitiveDescriptor(
-        obj_, runtime_, bHandle_, bDescObjHandle_, bTmpNameStorage_, bDesc);
-
     if (aDescObjHandle_) {
       if (LLVM_LIKELY(!aDesc.flags.proxyObject)) {
         auto res = JSObject::getComputedPropertyValue_RJS(
@@ -1135,6 +1131,11 @@ class StandardSortModel : public SortModel {
         }
       }
     }
+
+    ComputedPropertyDescriptor bDesc;
+    JSObject::getComputedPrimitiveDescriptor(
+        obj_, runtime_, bHandle_, bDescObjHandle_, bTmpNameStorage_, bDesc);
+
     if (bDescObjHandle_) {
       if (LLVM_LIKELY(!bDesc.flags.proxyObject)) {
         auto res = JSObject::getComputedPropertyValue_RJS(


[JSC] RegExpGlobalData::performMatch issue leading to OOB read
https://bugs.webkit.org/show_bug.cgi?id=254930
rdar://107436732

Reviewed by Alexey Shvayka.

Fixed two issues:
1) In YarrInterpreter.cpp::matchAssertionBOL() we were advancing the string position for non-BMP
   characters.  Since it is an assertion, we shouldn't advance the character position.
   Made the same fix to matchAssertionEOL().
2) In StringPrototype.cpp::replaceUsingRegExpSearch(), we need to advance past both elements of
   a non-BMP character for the case where the RegExp match is empty.

* JSTests/stress/string-replace-regexp-matchBOL-correct-advancing.js: New test.
* Source/JavaScriptCore/runtime/StringPrototype.cpp:
(JSC::replaceUsingRegExpSearch):
* Source/JavaScriptCore/yarr/YarrInterpreter.cpp:
(JSC::Yarr::Interpreter::InputStream::readCheckedDontAdvance):
(JSC::Yarr::Interpreter::matchAssertionBOL):
(JSC::Yarr::Interpreter::matchAssertionEOL):

Canonical link: https://commits.webkit.org/259548.551@safari-7615-branch

@@ -488,6 +488,11 @@ static ALWAYS_INLINE JSString* replaceUsingRegExpSearch(
                 startPosition++;
                 if (startPosition > sourceLen)
                     break;
+                if (U16_IS_LEAD(source[startPosition - 1]) && U16_IS_TRAIL(source[startPosition])) {
+                    startPosition++;
+                    if (startPosition > sourceLen)
+                        break;
+                }
             }
         }
     } else {
@@ -567,6 +572,11 @@ static ALWAYS_INLINE JSString* replaceUsingRegExpSearch(
                 startPosition++;
                 if (startPosition > sourceLen)
                     break;
+                if (U16_IS_LEAD(source[startPosition - 1]) && U16_IS_TRAIL(source[startPosition])) {
+                    startPosition++;
+                    if (startPosition > sourceLen)
+                        break;
+                }
             }
         } while (global);
     }


[chttp2] Fix fuzzer found bug (#32507)

<!--

If you know who should review your pull request, please assign it to
that
person, otherwise the pull request would get assigned randomly.

If your pull request is for a specific language, please add the
appropriate
lang label.

-->

@@ -803,7 +803,7 @@ class HPackParser::Parser {

     template <typename Key, typename Value>
     void Encode(Key, const Value& value) {
-      AddToSummary(Key::key(), Key::Encode(value).size());
+      AddToSummary(Key::key(), EncodedSizeOfKey(Key(), value));
     }

    private:


Bug 1783536 - Prevent document.cookie de-sync from cookie jar when setting secure cookies. r=dveditz,necko-reviewers

Secure cookie names are now sent to insecure-origin content processes so they are
able to prevent cookie setting when there is a pre-existing secure cookie
on another process. This will prevent each content process document.cookie from
getting de-synchronized from the cookie jar.

Differential Revision: https://phabricator.services.mozilla.com/D157537

@@ -50,8 +50,10 @@ void CookieServiceParent::RemoveBatchDeletedCookies(nsIArray* aCookieList) {
     const auto& cookie = xpcCookie->AsCookie();
     attrs = cookie.OriginAttributesRef();
     cookieStruct = cookie.ToIPC();
-    if (cookie.IsHttpOnly()) {
-      // Child only needs to exist if an HttpOnly cookie exists, not its value
+
+    // Child only needs to know HttpOnly cookies exists, not its value
+    // Same for Secure cookies going to a process for an insecure site.
+    if (cookie.IsHttpOnly() || !InsecureCookieOrSecureOrigin(cookie)) {
       cookieStruct.value() = "";
     }
     cookieStructList.AppendElement(cookieStruct);
@@ -65,7 +67,10 @@ void CookieServiceParent::RemoveAll() { Unused << SendRemoveAll(); }
 void CookieServiceParent::RemoveCookie(const Cookie& cookie) {
   const OriginAttributes& attrs = cookie.OriginAttributesRef();
   CookieStruct cookieStruct = cookie.ToIPC();
-  if (cookie.IsHttpOnly()) {
+
+  // Child only needs to know HttpOnly cookies exists, not its value
+  // Same for Secure cookies going to a process for an insecure site.
+  if (cookie.IsHttpOnly() || !InsecureCookieOrSecureOrigin(cookie)) {
     cookieStruct.value() = "";
   }
   Unused << SendRemoveCookie(cookieStruct, attrs);
@@ -74,18 +79,32 @@ void CookieServiceParent::RemoveCookie(const Cookie& cookie) {
 void CookieServiceParent::AddCookie(const Cookie& cookie) {
   const OriginAttributes& attrs = cookie.OriginAttributesRef();
   CookieStruct cookieStruct = cookie.ToIPC();
-  if (cookie.IsHttpOnly()) {
+
+  // Child only needs to know HttpOnly cookies exists, not its value
+  // Same for Secure cookies going to a process for an insecure site.
+  if (cookie.IsHttpOnly() || !InsecureCookieOrSecureOrigin(cookie)) {
     cookieStruct.value() = "";
   }
   Unused << SendAddCookie(cookieStruct, attrs);
 }

-bool CookieServiceParent::CookieMatchesContentList(const Cookie& cookie) {
+bool CookieServiceParent::ContentProcessHasCookie(const Cookie& cookie) {
   nsCString baseDomain;
   // CookieStorage notifications triggering this won't fail to get base domain
   MOZ_ALWAYS_SUCCEEDS(CookieCommons::GetBaseDomainFromHost(
       mTLDService, cookie.Host(), baseDomain));

+  CookieKey cookieKey(baseDomain, cookie.OriginAttributesRef());
+  return mCookieKeysInContent.MaybeGet(cookieKey).isSome();
+}
+
+bool CookieServiceParent::InsecureCookieOrSecureOrigin(const Cookie& cookie) {
+  nsCString baseDomain;
+  // CookieStorage notifications triggering this won't fail to get base domain
+  MOZ_ALWAYS_SUCCEEDS(CookieCommons::GetBaseDomainFromHost(
+      mTLDService, cookie.Host(), baseDomain));
+
+  // cookie is insecure or cookie is associated with a secure-origin process
   CookieKey cookieKey(baseDomain, cookie.OriginAttributesRef());
   if (Maybe<bool> allowSecure = mCookieKeysInContent.MaybeGet(cookieKey)) {
     return (!cookie.IsSecure() || *allowSecure);
@@ -124,9 +143,9 @@ void CookieServiceParent::TrackCookieLoad(nsIChannel* aChannel) {
       result.contains(ThirdPartyAnalysis::IsThirdPartySocialTrackingResource),
       result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted),
       rejectedReason, isSafeTopLevelNav, isSameSiteForeign,
-      hadCrossSiteRedirects, false, attrs, foundCookieList);
+      hadCrossSiteRedirects, false, true, attrs, foundCookieList);
   nsTArray<CookieStruct> matchingCookiesList;
-  SerialializeCookieList(foundCookieList, matchingCookiesList);
+  SerializeCookieList(foundCookieList, matchingCookiesList, uri);
   Unused << SendTrackCookiesLoad(matchingCookiesList, attrs);
 }

@@ -150,17 +169,26 @@ void CookieServiceParent::UpdateCookieInContentList(
 }

 // static
-void CookieServiceParent::SerialializeCookieList(
+void CookieServiceParent::SerializeCookieList(
     const nsTArray<Cookie*>& aFoundCookieList,
-    nsTArray<CookieStruct>& aCookiesList) {
+    nsTArray<CookieStruct>& aCookiesList, nsIURI* aHostURI) {
   for (uint32_t i = 0; i < aFoundCookieList.Length(); i++) {
     Cookie* cookie = aFoundCookieList.ElementAt(i);
     CookieStruct* cookieStruct = aCookiesList.AppendElement();
     *cookieStruct = cookie->ToIPC();
+
+    // clear http-only cookie values
     if (cookie->IsHttpOnly()) {
       // Value only needs to exist if an HttpOnly cookie exists.
       cookieStruct->value() = "";
     }
+
+    // clear secure cookie values in insecure context
+    bool potentiallyTurstworthy =
+        nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(aHostURI);
+    if (cookie->IsSecure() && !potentiallyTurstworthy) {
+      cookieStruct->value() = "";
+    }
   }
 }

@@ -189,9 +217,9 @@ IPCResult CookieServiceParent::RecvPrepareCookieList(
       aHost, nullptr, aIsForeign, aIsThirdPartyTrackingResource,
       aIsThirdPartySocialTrackingResource, aStorageAccessPermissionGranted,
       aRejectedReason, aIsSafeTopLevelNav, aIsSameSiteForeign,
-      aHadCrossSiteRedirects, false, aAttrs, foundCookieList);
+      aHadCrossSiteRedirects, false, true, aAttrs, foundCookieList);
   nsTArray<CookieStruct> matchingCookiesList;
-  SerialializeCookieList(foundCookieList, matchingCookiesList);
+  SerializeCookieList(foundCookieList, matchingCookiesList, aHost);
   Unused << SendTrackCookiesLoad(matchingCookiesList, aAttrs);
   return IPC_OK();
 }


Bug 1816158 - Part 1: Disallow GC while iterating global's debugger vector r=sfink

GC can mutate this vector so don't allow that while we are iterating. I think
it would be safe to use index-based iteration but it's safer to just ban it
entirely.

This fixes the crash produced by the testcase.

Differential Revision: https://phabricator.services.mozilla.com/D169701

@@ -205,7 +205,7 @@ static inline void MaybeVerifyBarriers(JSContext* cx, bool always = false) {}
  * This works by updating the |JSContext::suppressGC| counter which is checked
  * at the start of GC.
  */
-class MOZ_RAII JS_HAZ_GC_SUPPRESSED AutoSuppressGC {
+class MOZ_RAII JS_HAZ_GC_SUPPRESSED AutoSuppressGC : public JS::AutoRequireNoGC {
   int32_t& suppressGC_;

  public:


Bug 1801248 - Fix up pointer arithmetic. r=gfx-reviewers,lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D162496

@@ -407,7 +407,7 @@ bool gfxTextRun::GetAdjustedSpacingArray(
   memset(aSpacing->Elements(), 0, sizeof(gfxFont::Spacing) * spacingOffset);
   GetAdjustedSpacing(this, aSpacingRange, aProvider,
                      aSpacing->Elements() + spacingOffset);
-  memset(aSpacing->Elements() + aSpacingRange.end - aRange.start, 0,
+  memset(aSpacing->Elements() + spacingOffset + aSpacingRange.Length(), 0,
          sizeof(gfxFont::Spacing) * (aRange.end - aSpacingRange.end));
   return true;
 }


Fix array overflow for headings using roman numerals (Issue #433)

@@ -87,17 +97,17 @@ format_number(int  n,		/* I - Number */
         break;

     case 'i' :
-        if (n >= 1000)
-	  buffer[0] = '\0';
-	else
-          snprintf(buffer, sizeof(buffer), "%s%s%s", hundreds[n / 100], tens[(n / 10) % 10], ones[n % 10]);
+        if (n >= 3000)
+          n = (n % 3000) + 1;
+
+	snprintf(buffer, sizeof(buffer), "%s%s%s", hundreds[n / 100], tens[(n / 10) % 10], ones[n % 10]);
         break;

     case 'I' :
-        if (n >= 1000)
-	  buffer[0] = '\0';
-	else
-          snprintf(buffer, sizeof(buffer), "%s%s%s", HUNDREDS[n / 100], TENS[(n / 10) % 10], ONES[n % 10]);
+        if (n >= 3000)
+          n = (n % 3000) + 1;
+
+	snprintf(buffer, sizeof(buffer), "%s%s%s", HUNDREDS[n / 100], TENS[(n / 10) % 10], ONES[n % 10]);
         break;
   }


@@ -219,6 +219,13 @@ namespace NSJSBase
 #ifdef V8_INSPECTOR
 		v8_debug::disposeInspector(m_internal->m_context);
 #endif
+		unsigned int nEmbedDataCount = m_internal->m_isolate->GetNumberOfDataSlots();
+		for (unsigned int i = 0; i < nEmbedDataCount; ++i)
+		{
+			CIsolateAdditionalData* pAdditionData = (CIsolateAdditionalData*)m_internal->m_isolate->GetData(i);
+			delete pAdditionData;
+		}
+
 		m_internal->m_isolate->Dispose();
 		m_internal->m_isolate = NULL;
 	}


Fix hashing (#84)

* Revert "Fix hash calculation (#62)"

This reverts commit d16e9ec2b4d54c1333137ae34f011e9eb3e0b962.

* test: stuffed PE tests

Signed-off-by: William Woodruff <william@trailofbits.com>

* uthenticode-test: re-add failing hashes

These hashes are correct; this can't be merged until these tests pass.

Signed-off-by: William Woodruff <william@trailofbits.com>

* src, test: don't support checksums on unsigned exes

Signed-off-by: William Woodruff <william@trailofbits.com>

* test/assets: stuffing example

Signed-off-by: William Woodruff <william@trailofbits.com>

* uthenticode: fix hashing on trailing data

Signed-off-by: William Woodruff <william@trailofbits.com>

* uthenticode: safer buffer operations

Signed-off-by: William Woodruff <william@trailofbits.com>

* uthenticode: free trailer_buf once we're done with it

Signed-off-by: William Woodruff <william@trailofbits.com>

---------

Signed-off-by: William Woodruff <william@trailofbits.com>

@@ -111,3 +111,19 @@ class MissingEKUTest : public ::testing::Test {

   peparse::parsed_pe *pe{nullptr};
 };
+
+class StuffingTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    auto *file = UTHENTICODE_TEST_ASSETS "/YourPhone.exe";
+
+    pe = peparse::ParsePEFromFile(file);
+    ASSERT_TRUE(pe != nullptr);
+  }
+
+  void TearDown() override {
+    peparse::DestructParsedPE(pe);
+  }
+
+  peparse::parsed_pe *pe{nullptr};
+};


@@ -532,13 +532,15 @@ inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
     Model->Coder.SubRange.LowCount=HiCnt;
     Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
     i=NumStats-Model->NumMasked;
-    pps--;
+
+    // 2022.12.02: we removed pps-- here and changed the code below to avoid
+    // "array subscript -1 is outside array bounds" warning in some compilers.
     do
     {
-      pps++;
       if (pps>=ps+ASIZE(ps)) // Extra safety check.
         return false;
       Model->CharMask[(*pps)->Symbol]=Model->EscCount;
+      pps++;
     } while ( --i );
     psee2c->Summ += Model->Coder.SubRange.scale;
     Model->NumMasked = NumStats;


Fix UAF when exiting a nested run loop in TabDragContextImpl::OnGestureEvent.

OnGestureEvent may call ContinueDrag, which may run a nested run loop. After the nested run loop returns, multiple seconds of time may have passed, and the world may be in a very different state; in particular, the window that contains this TabDragContext may have closed.

This CL checks if this has happened, and returns early in that case.

Bug: 1453465
Change-Id: I6095c0afeb5aa5f422717f1bbd93b96175e52afa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4657527
Reviewed-by: Darryl James <dljames@chromium.org>
Commit-Queue: Taylor Bergquist <tbergquist@chromium.org>
Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#1164449}

@@ -278,7 +278,8 @@ class TabStrip : public views::View,
       TabSlotView* source,
       const ui::LocatedEvent& event,
       const ui::ListSelectionModel& original_selection) override;
-  void ContinueDrag(views::View* view, const ui::LocatedEvent& event) override;
+  [[nodiscard]] Liveness ContinueDrag(views::View* view,
+                                      const ui::LocatedEvent& event) override;
   bool EndDrag(EndDragReason reason) override;
   Tab* GetTabAt(const gfx::Point& point) override;
   const Tab* GetAdjacentTab(const Tab* tab, int offset) override;


Bug 1846694: Additional validation in RecordedSourceSurfaceCreation. r=gfx-reviewers,jrmuizel

Differential Revision: https://phabricator.services.mozilla.com/D185354

@@ -3206,6 +3206,13 @@ RecordedSourceSurfaceCreation::RecordedSourceSurfaceCreation(S& aStream)
   ReadElement(aStream, mSize);
   ReadElementConstrained(aStream, mFormat, SurfaceFormat::A8R8G8B8_UINT32,
                          SurfaceFormat::UNKNOWN);
+
+  if (!Factory::AllowedSurfaceSize(mSize)) {
+    gfxCriticalNote << "RecordedSourceSurfaceCreation read invalid size "
+                    << mSize;
+    aStream.SetIsBad();
+  }
+
   if (!aStream.good()) {
     return;
   }


MINIFICPP-2170 Fix system certificate store usage in SSLContextService on Linux

Use utils::getDefaultCAFile() in the SSLContextService to find the system CA
certificate store file, as the compiled-in default value is usually wrong.
If the system CA certificate store file is still not found, you can set the
SSL_CERT_DIR or SSL_CERT_FILE environment variables to tell OpenSSL where
the certificates are.

Also: fix the incorrect handling of InvokeHTTP::DisablePeerVerification.
Signed-off-by: Gabor Gyimesi <gamezbird@gmail.com>

This closes #1620

@@ -44,8 +44,8 @@ HTTPClient::HTTPClient(std::string url, std::shared_ptr<minifi::controllers::SSL
   http_session_.reset(curl_easy_init());
 }

-HTTPClient::HTTPClient(std::string name, const utils::Identifier& uuid)
-    : core::Connectable(std::move(name), uuid) {
+HTTPClient::HTTPClient(std::string_view name, const utils::Identifier& uuid)
+    : core::Connectable(name, uuid) {
   http_session_.reset(curl_easy_init());
 }

@@ -125,7 +125,11 @@ void HTTPClient::initialize(std::string method, std::string url, std::shared_ptr
 }

 void HTTPClient::setPeerVerification(bool peer_verification) {
-  logger_->log_debug("%s peer verification", peer_verification ? "Enabling" : "Disabling");
+  if (peer_verification) {
+    logger_->log_debug("Enabling peer verification");
+  } else {
+    logger_->log_warn("Disabling peer verification: the authenticity of https servers will not be verified!");
+  }
   curl_easy_setopt(http_session_.get(), CURLOPT_SSL_VERIFYPEER, peer_verification);
 }

@@ -458,26 +462,22 @@ int HTTPClient::onProgress(void *clientp, curl_off_t /*dltotal*/, curl_off_t dln
 void HTTPClient::configure_secure_connection() {
 #ifdef OPENSSL_SUPPORT
   if (ssl_context_service_) {
-    logger_->log_debug("Using certificate file \"%s\"", ssl_context_service_->getCertificateFile().string());
-    logger_->log_debug("Using private key file \"%s\"", ssl_context_service_->getPrivateKeyFile().string());
-    logger_->log_debug("Using CA certificate file \"%s\"", ssl_context_service_->getCACertificate().string());
-
     curl_easy_setopt(http_session_.get(), CURLOPT_SSL_CTX_FUNCTION, &configure_ssl_context);
     curl_easy_setopt(http_session_.get(), CURLOPT_SSL_CTX_DATA, static_cast<void *>(ssl_context_service_.get()));
     curl_easy_setopt(http_session_.get(), CURLOPT_CAINFO, nullptr);
     curl_easy_setopt(http_session_.get(), CURLOPT_CAPATH, nullptr);
   } else {
-    static const auto default_ca_path = utils::getDefaultCAPath();
+    static const auto default_ca_file = utils::getDefaultCAFile();

-    if (default_ca_path)
-      logger_->log_debug("Using CA certificate file \"%s\"", default_ca_path->string());
+    if (default_ca_file)
+      logger_->log_debug("Using CA certificate file \"%s\"", std::string(*default_ca_file));
     else
       logger_->log_error("Could not find valid CA certificate file");

     curl_easy_setopt(http_session_.get(), CURLOPT_SSL_CTX_FUNCTION, nullptr);
     curl_easy_setopt(http_session_.get(), CURLOPT_SSL_CTX_DATA, nullptr);
-    if (default_ca_path)
-      curl_easy_setopt(http_session_.get(), CURLOPT_CAINFO, default_ca_path->string().c_str());
+    if (default_ca_file)
+      curl_easy_setopt(http_session_.get(), CURLOPT_CAINFO, std::string(*default_ca_file).c_str());
     else
       curl_easy_setopt(http_session_.get(), CURLOPT_CAINFO, nullptr);
     curl_easy_setopt(http_session_.get(), CURLOPT_CAPATH, nullptr);


null-pointer check in debug output (fixes #426)

@@ -1277,14 +1277,23 @@ void slice_segment_header::dump_slice_segment_header(const decoder_context* ctx,
 #define LOG3(t,d1,d2,d3) log2fh(fh, t,d1,d2,d3)
 #define LOG4(t,d1,d2,d3,d4) log2fh(fh, t,d1,d2,d3,d4)

+  LOG0("----------------- SLICE -----------------\n");
+
   const pic_parameter_set* pps = ctx->get_pps(slice_pic_parameter_set_id);
+  if (!pps) {
+    LOG0("invalid PPS referenced\n");
+    return;
+  }
   assert(pps->pps_read); // TODO: error handling

   const seq_parameter_set* sps = ctx->get_sps((int)pps->seq_parameter_set_id);
+  if (!sps) {
+    LOG0("invalid SPS referenced\n");
+    return;
+  }
   assert(sps->sps_read); // TODO: error handling

-  LOG0("----------------- SLICE -----------------\n");
   LOG1("first_slice_segment_in_pic_flag      : %d\n", first_slice_segment_in_pic_flag);
   if (ctx->get_nal_unit_type() >= NAL_UNIT_BLA_W_LP &&
       ctx->get_nal_unit_type() <= NAL_UNIT_RESERVED_IRAP_VCL23) {


Remove support for Gopher protocol (#1092)

Gopher code quality remains too low for production use in most
environments. The code is a persistent source of vulnerabilities and
fixing it requires significant effort. We should not be spending scarce
Project resources on improving that code, especially given the lack of
strong demand for Gopher support.

With this change, Gopher requests will be handled like any other request
with an unknown (to Squid) protocol. For example, HTTP requests with
Gopher URI scheme result in ERR_UNSUP_REQ.

Default Squid configuration still considers TCP port 70 "safe". The
corresponding Safe_ports ACL rule has not been removed for consistency
sake: We consider WAIS port safe even though Squid refuses to forward
WAIS requests:

    acl Safe_ports port 70          # gopher
    acl Safe_ports port 210         # wais

@@ -34,7 +34,6 @@
 #include "fde.h"
 #include "format/Token.h"
 #include "FwdState.h"
-#include "gopher.h"
 #include "helper.h"
 #include "helper/Reply.h"
 #include "http.h"
@@ -907,9 +906,6 @@ clientHierarchical(ClientHttpRequest * http)
     if (request->url.getScheme() == AnyP::PROTO_HTTP)
         return method.respMaybeCacheable();

-    if (request->url.getScheme() == AnyP::PROTO_GOPHER)
-        return gopherCachable(request);
-
     if (request->url.getScheme() == AnyP::PROTO_CACHE_OBJECT)
         return 0;


Merge pull request from GHSA-hrw9-ggg3-3r4r

Fix integer overflow in BmffImage::brotliUncompress

@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+from system_tests import CaseMeta, path
+
+class BrotliUncompressOutOfBoundsWrite(metaclass=CaseMeta):
+    """
+    Regression test for the bug described in:
+    https://github.com/Exiv2/exiv2/security/advisories/GHSA-hrw9-ggg3-3r4r
+    """
+    url = "https://github.com/Exiv2/exiv2/security/advisories/GHSA-hrw9-ggg3-3r4r"
+
+    filename = path("$data_path/issue_ghsa_hrw9_ggg3_3r4r_poc.jpg")
+    commands = ["$exiv2 $filename"]
+    stdout = [""]
+    stderr = [
+"""Exiv2 exception in print action for file $filename:
+$kerFailedToReadImageData
+"""]
+    retval = [1]


Fix validation of certificates with CN=* (#1523)

The bug was discovered and detailed by Joshua Rogers at
https://megamansec.github.io/Squid-Security-Audit/
where it was filed as "Buffer UnderRead in SSL CN Parsing".

@@ -175,6 +175,10 @@ urlInitialize(void)
     assert(0 == matchDomainName("*.foo.com", ".foo.com", mdnHonorWildcards));
     assert(0 != matchDomainName("*.foo.com", "foo.com", mdnHonorWildcards));

+    assert(0 != matchDomainName("foo.com", ""));
+    assert(0 != matchDomainName("foo.com", "", mdnHonorWildcards));
+    assert(0 != matchDomainName("foo.com", "", mdnRejectSubsubDomains));
+
     /* more cases? */
 }

@@ -828,6 +832,8 @@ matchDomainName(const char *h, const char *d, MatchDomainNameFlags flags)
         return -1;

     dl = strlen(d);
+    if (dl == 0)
+        return 1;

     /*
      * Start at the ends of the two strings and work towards the


[SECURITY-49] added a tool to re-key secrets

As an AdministrativeMonitor, it shows up in the manage Jenkins UI, and
allows the administrator to run a re-keying operation.

@@ -0,0 +1,33 @@
+package hudson.util;
+
+import hudson.Util;
+import org.junit.rules.ExternalResource;
+
+import java.security.SecureRandom;
+
+/**
+ * JUnit rule that cleans that sets a temporary {@link Secret#SECRET} value.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class MockSecretRule extends ExternalResource {
+
+    private String value;
+
+    @Override
+    protected void before() throws Throwable {
+        byte[] random = new byte[32];
+        sr.nextBytes(random);
+        value = Util.toHexString(random);
+        Secret.SECRET = value;
+    }
+
+    @Override
+    protected void after() {
+        if (!Secret.SECRET.equals(value))
+            throw new IllegalStateException("Someone tinkered with Secret.SECRET");
+        Secret.SECRET = null;
+    }
+
+    private static final SecureRandom sr = new SecureRandom();
+}


[SECURITY-49] Deprecating Jenkins.getSecretKey()

We are replacing it by the ConfidentialStore class and the
ConfidentialKey class, which provides purpose-specific confidential
information that are separated from each other.

In this way, not all eggs are in one basket, and in case of a
compromise, the impact will contained.

Also replaced several insecure use of digest(secret|messsage) or
digest(message|secret) by HMAC.

@@ -23,10 +23,10 @@
  */
 package hudson.security;

+import jenkins.security.HMACConfidentialKey;
 import org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices;
 import org.acegisecurity.userdetails.UserDetails;
 import org.acegisecurity.Authentication;
-import org.apache.commons.codec.digest.DigestUtils;

 /**
  * {@link TokenBasedRememberMeServices} with modification so as not to rely
@@ -41,7 +41,7 @@
 public class TokenBasedRememberMeServices2 extends TokenBasedRememberMeServices {
     @Override
     protected String makeTokenSignature(long tokenExpiryTime, UserDetails userDetails) {
-        String expectedTokenSignature = DigestUtils.md5Hex(userDetails.getUsername() + ":" + tokenExpiryTime + ":"
+        String expectedTokenSignature = MAC.mac(userDetails.getUsername() + ":" + tokenExpiryTime + ":"
                 + "N/A" + ":" + getKey());
         return expectedTokenSignature;
     }
@@ -50,4 +50,9 @@ protected String makeTokenSignature(long tokenExpiryTime, UserDetails userDetail
     protected String retrievePassword(Authentication successfulAuthentication) {
         return "N/A";
     }
+
+    /**
+     * Used to compute the token signature securely.
+     */
+    private static final HMACConfidentialKey MAC = new HMACConfidentialKey(TokenBasedRememberMeServices.class,"mac");
 }


@@ -0,0 +1,144 @@
+package jenkins.security;
+
+import hudson.Util;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+/**
+ * {@link ConfidentialKey} that's used for creating a token by hashing some information with secret
+ * (such as <tt>hash(msg|secret)</tt>).
+ *
+ * <p>
+ * This provides more secure version of it by using HMAC.
+ * See http://rdist.root.org/2009/10/29/stop-using-unsafe-keyed-hashes-use-hmac/ for background.
+ * This implementation also never leaks the secret value to outside, so it makes it impossible
+ * for the careless caller to misuse the key (thus protecting ourselves from our own stupidity!)
+ *
+ * @author Kohsuke Kawaguchi
+ * @since 1.498
+ */
+public class HMACConfidentialKey extends ConfidentialKey {
+    private volatile SecretKey key;
+    private final int length;
+
+    /**
+     * @param length
+     *      Byte length of the HMAC code.
+     *      By default we use HMAC-SHA256, which produces 256bit (=32bytes) HMAC,
+     *      but if different use cases requires a shorter HMAC, specify the desired length here.
+     *      Note that when using {@link #mac(String)}, string encoding causes the length to double.
+     *      So if you want to get 16-letter HMAC, you specify 8 here.
+     */
+    public HMACConfidentialKey(String id, int length) {
+        super(id);
+        this.length = length;
+    }
+
+    /**
+     * Calls into {@link #HMACConfidentialKey(String, int)} with the longest possible HMAC length.
+     */
+    public HMACConfidentialKey(String id) {
+        this(id,Integer.MAX_VALUE);
+    }
+
+    /**
+     * Calls into {@link #HMACConfidentialKey(String, int)} by combining the class name and the shortName
+     * as the ID.
+     */
+    public HMACConfidentialKey(Class owner, String shortName, int length) {
+        this(owner.getName()+'.'+shortName,length);
+    }
+
+    public HMACConfidentialKey(Class owner, String shortName) {
+        this(owner,shortName,Integer.MAX_VALUE);
+    }
+
+
+    /**
+     * Computes the message authentication code for the specified byte sequence.
+     */
+    public byte[] mac(byte[] message) {
+        return chop(createMac().doFinal(message));
+    }
+
+    /**
+     * Convenience method for verifying the MAC code.
+     */
+    public boolean checkMac(byte[] message, byte[] mac) {
+        return Arrays.equals(mac(message),mac);
+    }
+
+    /**
+     * Computes the message authentication code and return it as a string.
+     * While redundant, often convenient.
+     */
+    public String mac(String message) {
+        try {
+            return Util.toHexString(mac(message.getBytes("UTF-8")));
+        } catch (UnsupportedEncodingException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * Verifies MAC constructed from {@link #mac(String)}
+     */
+    public boolean checkMac(String message, String mac) {
+        return mac(message).equals(mac);
+    }
+
+    private byte[] chop(byte[] mac) {
+        if (mac.length<=length)  return mac; // already too short
+
+        byte[] b = new byte[length];
+        System.arraycopy(mac,0,b,0,b.length);
+        return b;
+    }
+
+    /**
+     * Creates a new {@link Mac} object.
+     */
+    public Mac createMac() {
+        try {
+            Mac mac = Mac.getInstance(ALGORITHM);
+            mac.init(getKey());
+            return mac;
+        } catch (GeneralSecurityException e) {
+            // Javadoc says HmacSHA256 must be supported by every Java implementation.
+            throw new Error(ALGORITHM+" not supported?",e);
+        }
+    }
+
+    private SecretKey getKey() {
+        if (key==null) {
+            synchronized (this) {
+                if (key==null) {
+                    try {
+                        byte[] encoded = load();
+                        if (encoded==null) {
+                            KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
+                            SecretKey key = kg.generateKey();
+                            store(encoded=key.getEncoded());
+                        }
+                        key = new SecretKeySpec(encoded,ALGORITHM);
+                    } catch (IOException e) {
+                        throw new Error("Failed to load the key: "+getId(),e);
+                    } catch (NoSuchAlgorithmException e) {
+                        throw new Error("Failed to load the key: "+getId(),e);
+                    }
+                }
+            }
+        }
+        return key;
+    }
+
+    private static final String ALGORITHM = "HmacSHA256";
+}


https://issues.jboss.org/browse/WFK2-375 enhanced fix

git-svn-id: https://svn.jboss.org/repos/seam/branches/enterprise/WFK-2_1@15651 a9c07ecc-ef43-0410-a306-c911db474e88

@@ -21,6 +21,7 @@
 import org.jboss.seam.log.Logging;
 import org.jboss.seam.remoting.wrapper.Wrapper;
 import org.jboss.seam.servlet.ContextualHttpServletRequest;
+import org.jboss.seam.util.XML;

 /**
  * Unmarshals the calls from an HttpServletRequest, executes them in order and
@@ -67,7 +68,7 @@ public void handle(HttpServletRequest request, final HttpServletResponse respons
       log.debug("Processing remote request: " + requestData);

       // Parse the incoming request as XML
-      SAXReader xmlReader = new SAXReader();
+      SAXReader xmlReader = XML.getSafeSaxReader();
       Document doc = xmlReader.read( new StringReader(requestData) );
       final Element env = doc.getRootElement();
       final RequestContext ctx = unmarshalContext(env);


[FIXED SECURITY-108] Check job name created via CLI

@@ -72,6 +72,7 @@ protected int run() throws Exception {
             name = name.substring(i + 1);
         }

+        Jenkins.checkGoodName(name);
         ig.createProjectFromXML(name, stdin);
         return 0;
     }


[FIXED SECURITY-93] PasswordParameterDefinition should serve existing default value in encrypted form.
And strengthen functional tests (using configRoundTrip) to ensure that the same mistake is not made elsewhere.

@@ -28,6 +28,8 @@
 import org.kohsuke.stapler.DataBoundConstructor;
 import hudson.Extension;
 import hudson.util.Secret;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.DoNotUse;

 /**
  * Parameter whose value is a {@link Secret} and is hidden from the UI.
@@ -76,6 +78,11 @@ public String getDefaultValue() {
         return Secret.toString(defaultValue);
     }

+    @Restricted(DoNotUse.class) // used from Jelly
+    public Secret getDefaultValueAsSecret() {
+        return defaultValue;
+    }
+
     // kept for backward compatibility
     public void setDefaultValue(String defaultValue) {
         this.defaultValue = Secret.fromString(defaultValue);


[FIXED SECURITY-77] XSS in iconSize cookie.

@@ -766,7 +766,7 @@ public AsynchPeople(View parent) {

         {
             StaplerRequest req = Stapler.getCurrentRequest();
-            iconSize = req != null ? Functions.getCookie(req, "iconSize", "32x32") : "32x32";
+            iconSize = req != null ? Functions.validateIconSize(Functions.getCookie(req, "iconSize", "32x32")) : "32x32";
         }

         @Override protected void compute() throws Exception {


Adopted SecureRandom to avoid predicable random numbers in session

@@ -1,141 +1,142 @@
 /*
-    *
-    *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
-    *  *
-    *  *  Licensed under the Apache License, Version 2.0 (the "License");
-    *  *  you may not use this file except in compliance with the License.
-    *  *  You may obtain a copy of the License at
-    *  *
-    *  *       http://www.apache.org/licenses/LICENSE-2.0
-    *  *
-    *  *  Unless required by applicable law or agreed to in writing, software
-    *  *  distributed under the License is distributed on an "AS IS" BASIS,
-    *  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    *  *  See the License for the specific language governing permissions and
-    *  *  limitations under the License.
-    *  *
-    *  * For more information: http://www.orientechnologies.com
-    *
-    */
+ *
+ *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
+ *  *
+ *  *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  *  you may not use this file except in compliance with the License.
+ *  *  You may obtain a copy of the License at
+ *  *
+ *  *       http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  *  Unless required by applicable law or agreed to in writing, software
+ *  *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  *  See the License for the specific language governing permissions and
+ *  *  limitations under the License.
+ *  *
+ *  * For more information: http://www.orientechnologies.com
+ *
+ */
 package com.orientechnologies.orient.server.network.protocol.http;

 import com.orientechnologies.common.concur.resource.OSharedResourceAbstract;
- import com.orientechnologies.common.log.OLogManager;
- import com.orientechnologies.orient.core.Orient;
- import com.orientechnologies.orient.core.config.OGlobalConfiguration;
-
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Random;
- import java.util.TimerTask;
+import com.orientechnologies.common.log.OLogManager;
+import com.orientechnologies.orient.core.Orient;
+import com.orientechnologies.orient.core.config.OGlobalConfiguration;
+
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Random;
+import java.util.TimerTask;

 /**
-  * Handles the HTTP sessions such as a real HTTP Server.
-  *
-  * @author Luca Garulli
-  */
- public class OHttpSessionManager extends OSharedResourceAbstract {
-   private static final OHttpSessionManager instance = new OHttpSessionManager();
-   private Map<String, OHttpSession>        sessions = new HashMap<String, OHttpSession>();
-   private int                              expirationTime;
-   private Random                           random   = new Random();
-
-   protected OHttpSessionManager() {
-     expirationTime = OGlobalConfiguration.NETWORK_HTTP_SESSION_EXPIRE_TIMEOUT.getValueAsInteger() * 1000;
-
-     Orient.instance().scheduleTask(new TimerTask() {
-       @Override
-       public void run() {
-         final int expired = checkSessionsValidity();
-         if (expired > 0)
-           OLogManager.instance().debug(this, "Removed %d session because expired", expired);
-       }
-     }, expirationTime, expirationTime);
-   }
-
-   public int checkSessionsValidity() {
-     int expired = 0;
-
-     acquireExclusiveLock();
-     try {
-       final long now = System.currentTimeMillis();
-
-       Entry<String, OHttpSession> s;
-       for (Iterator<Map.Entry<String, OHttpSession>> it = sessions.entrySet().iterator(); it.hasNext();) {
-         s = it.next();
-
-         if (now - s.getValue().getUpdatedOn() > expirationTime) {
-           // REMOVE THE SESSION
-           it.remove();
-           expired++;
-         }
-       }
-
-     } finally {
-       releaseExclusiveLock();
-     }
-
-     return expired;
-   }
-
-   public OHttpSession[] getSessions() {
-     acquireSharedLock();
-     try {
-
-       return (OHttpSession[]) sessions.values().toArray(new OHttpSession[sessions.size()]);
-
-     } finally {
-       releaseSharedLock();
-     }
-   }
-
-   public OHttpSession getSession(final String iId) {
-     acquireSharedLock();
-     try {
-
-       final OHttpSession sess = sessions.get(iId);
-       if (sess != null)
-         sess.updateLastUpdatedOn();
-       return sess;
-
-     } finally {
-       releaseSharedLock();
-     }
-   }
-
-   public String createSession(final String iDatabaseName, final String iUserName, final String iUserPassword) {
-     acquireExclusiveLock();
-     try {
-       final String id = "OS" + System.currentTimeMillis() + random.nextLong();
-       sessions.put(id, new OHttpSession(id, iDatabaseName, iUserName, iUserPassword));
-       return id;
-
-     } finally {
-       releaseExclusiveLock();
-     }
-   }
-
-   public OHttpSession removeSession(final String iSessionId) {
-     acquireExclusiveLock();
-     try {
-       return sessions.remove(iSessionId);
-
-     } finally {
-       releaseExclusiveLock();
-     }
-   }
-
-   public int getExpirationTime() {
-     return expirationTime;
-   }
-
-   public void setExpirationTime(int expirationTime) {
-     this.expirationTime = expirationTime;
-   }
-
-   public static OHttpSessionManager getInstance() {
-     return instance;
-   }
- }
+ * Handles the HTTP sessions such as a real HTTP Server.
+ *
+ * @author Luca Garulli
+ */
+public class OHttpSessionManager extends OSharedResourceAbstract {
+  private static final OHttpSessionManager instance = new OHttpSessionManager();
+  private Map<String, OHttpSession>        sessions = new HashMap<String, OHttpSession>();
+  private int                              expirationTime;
+  private Random                           random   = new SecureRandom();
+
+  protected OHttpSessionManager() {
+    expirationTime = OGlobalConfiguration.NETWORK_HTTP_SESSION_EXPIRE_TIMEOUT.getValueAsInteger() * 1000;
+
+    Orient.instance().scheduleTask(new TimerTask() {
+      @Override
+      public void run() {
+        final int expired = checkSessionsValidity();
+        if (expired > 0)
+          OLogManager.instance().debug(this, "Removed %d session because expired", expired);
+      }
+    }, expirationTime, expirationTime);
+  }
+
+  public int checkSessionsValidity() {
+    int expired = 0;
+
+    acquireExclusiveLock();
+    try {
+      final long now = System.currentTimeMillis();
+
+      Entry<String, OHttpSession> s;
+      for (Iterator<Map.Entry<String, OHttpSession>> it = sessions.entrySet().iterator(); it.hasNext();) {
+        s = it.next();
+
+        if (now - s.getValue().getUpdatedOn() > expirationTime) {
+          // REMOVE THE SESSION
+          it.remove();
+          expired++;
+        }
+      }
+
+    } finally {
+      releaseExclusiveLock();
+    }
+
+    return expired;
+  }
+
+  public OHttpSession[] getSessions() {
+    acquireSharedLock();
+    try {
+
+      return (OHttpSession[]) sessions.values().toArray(new OHttpSession[sessions.size()]);
+
+    } finally {
+      releaseSharedLock();
+    }
+  }
+
+  public OHttpSession getSession(final String iId) {
+    acquireSharedLock();
+    try {
+
+      final OHttpSession sess = sessions.get(iId);
+      if (sess != null)
+        sess.updateLastUpdatedOn();
+      return sess;
+
+    } finally {
+      releaseSharedLock();
+    }
+  }
+
+  public String createSession(final String iDatabaseName, final String iUserName, final String iUserPassword) {
+    acquireExclusiveLock();
+    try {
+      final String id = "OS" + System.currentTimeMillis() + random.nextLong();
+      sessions.put(id, new OHttpSession(id, iDatabaseName, iUserName, iUserPassword));
+      return id;
+
+    } finally {
+      releaseExclusiveLock();
+    }
+  }
+
+  public OHttpSession removeSession(final String iSessionId) {
+    acquireExclusiveLock();
+    try {
+      return sessions.remove(iSessionId);
+
+    } finally {
+      releaseExclusiveLock();
+    }
+  }
+
+  public int getExpirationTime() {
+    return expirationTime;
+  }
+
+  public void setExpirationTime(int expirationTime) {
+    this.expirationTime = expirationTime;
+  }
+
+  public static OHttpSessionManager getInstance() {
+    return instance;
+  }
+}


Merge pull request #9700 from JiYou/fix-monitor-crush

mon: Monitor: validate prefix on handle_command()

Reviewed-by: Sage Weil <sage@redhat.com>
Reviewed-by: Joao Eduardo Luis <joao@suse.de>

@@ -48,6 +48,41 @@ TEST(LibRadosCmd, MonDescribe) {
   rados_buffer_free(buf);
   rados_buffer_free(st);

+  cmd[0] = (char *)"";
+  ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "{}", 2, &buf, &buflen, &st, &stlen));
+  rados_buffer_free(buf);
+  rados_buffer_free(st);
+
+  cmd[0] = (char *)"{}";
+  ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
+  rados_buffer_free(buf);
+  rados_buffer_free(st);
+
+  cmd[0] = (char *)"{\"abc\":\"something\"}";
+  ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
+  rados_buffer_free(buf);
+  rados_buffer_free(st);
+
+  cmd[0] = (char *)"{\"prefix\":\"\"}";
+  ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
+  rados_buffer_free(buf);
+  rados_buffer_free(st);
+
+  cmd[0] = (char *)"{\"prefix\":\"    \"}";
+  ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
+  rados_buffer_free(buf);
+  rados_buffer_free(st);
+
+  cmd[0] = (char *)"{\"prefix\":\";;;,,,;;,,\"}";
+  ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
+  rados_buffer_free(buf);
+  rados_buffer_free(st);
+
+  cmd[0] = (char *)"{\"prefix\":\"extra command\"}";
+  ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
+  rados_buffer_free(buf);
+  rados_buffer_free(st);
+
   cmd[0] = (char *)"{\"prefix\":\"mon_status\"}";
   ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
   ASSERT_LT(0u, buflen);


DATAJPA-965 - Fix potential blind SQL injection in Sort when used in combination with @Query.

We now decline sort expressions that contain functions such as ORDER BY LENGTH(name) when used with repository having a String query defined via the @Query annotation.

Think of a query method as follows:

@Query("select p from Person p where LOWER(p.lastname) = LOWER(:lastname)")
List<Person> findByLastname(@Param("lastname") String lastname, Sort sort);

Calls to findByLastname("lannister", new Sort("LENGTH(firstname)")) from now on throw an Exception indicating function calls are not allowed within the _ORDER BY_ clause. However you still can use JpaSort.unsafe("LENGTH(firstname)") to restore the behavior.

Kudos to Niklas Särökaari, Joona Immonen, Arto Santala, Antti Virtanen, Michael Holopainen and Antti Ahola who brought this to our attention.

@@ -1,5 +1,5 @@
 /*
- * Copyright 2013-2015 the original author or authors.
+ * Copyright 2013-2016 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
 import org.springframework.data.domain.Sort;
 import org.springframework.data.domain.Sort.Direction;
 import org.springframework.data.domain.Sort.Order;
+import org.springframework.data.jpa.domain.JpaSort.JpaOrder;
 import org.springframework.data.jpa.domain.JpaSort.Path;
 import org.springframework.data.jpa.domain.sample.Address_;
 import org.springframework.data.jpa.domain.sample.MailMessage_;
@@ -47,6 +48,7 @@
  * @see DATAJPA-12
  * @author Thomas Darimont
  * @author Oliver Gierke
+ * @author Christoph Strobl
  */
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration("classpath:infrastructure.xml")
@@ -173,4 +175,56 @@ public void buildsUpPathForPluralAttributesCorrectly() {
 		assertThat(new JpaSort(path(User_.colleagues).dot(User_.roles).dot(Role_.name)), //
 				hasItem(new Order(ASC, "colleagues.roles.name")));
 	}
+
+	/**
+	 * @see DATAJPA-???
+	 */
+	@Test
+	public void createsUnsafeSortCorrectly() {
+
+		JpaSort sort = JpaSort.unsafe(DESC, "foo.bar");
+
+		assertThat(sort, hasItem(new Order(DESC, "foo.bar")));
+		assertThat(sort.getOrderFor("foo.bar"), is(instanceOf(JpaOrder.class)));
+	}
+
+	/**
+	 * @see DATAJPA-???
+	 */
+	@Test
+	public void createsUnsafeSortWithMultiplePropertiesCorrectly() {
+
+		JpaSort sort = JpaSort.unsafe(DESC, "foo.bar", "spring.data");
+
+		assertThat(sort, hasItems(new Order(DESC, "foo.bar"), new Order(DESC, "spring.data")));
+		assertThat(sort.getOrderFor("foo.bar"), is(instanceOf(JpaOrder.class)));
+		assertThat(sort.getOrderFor("spring.data"), is(instanceOf(JpaOrder.class)));
+	}
+
+	/**
+	 * @see DATAJPA-???
+	 */
+	@Test
+	public void combinesSafeAndUnsafeSortCorrectly() {
+
+		JpaSort sort = new JpaSort(path(User_.colleagues).dot(User_.roles).dot(Role_.name)).andUnsafe(DESC, "foo.bar");
+
+		assertThat(sort, hasItems(new Order(ASC, "colleagues.roles.name"), new Order(DESC, "foo.bar")));
+		assertThat(sort.getOrderFor("colleagues.roles.name"), is(not(instanceOf(JpaOrder.class))));
+		assertThat(sort.getOrderFor("foo.bar"), is(instanceOf(JpaOrder.class)));
+	}
+
+	/**
+	 * @see DATAJPA-???
+	 */
+	@Test
+	public void combinesUnsafeAndSafeSortCorrectly() {
+
+		Sort sort = JpaSort.unsafe(DESC, "foo.bar").and(ASC, path(User_.colleagues).dot(User_.roles).dot(Role_.name));
+
+		assertThat(sort, hasItems(new Order(ASC, "colleagues.roles.name"), new Order(DESC, "foo.bar")));
+		assertThat(sort.getOrderFor("colleagues.roles.name"), is(not(instanceOf(JpaOrder.class))));
+		assertThat(sort.getOrderFor("foo.bar"), is(instanceOf(JpaOrder.class)));
+	}
+
 }


LPS-27741 Add security by plugin context execution to template engines

- We have to initialize/destroy a new template context specific to each plugin (keyed by ClassLoader of the plugin)
- Add/Replaced helper utilities to support classloading control (and access to classes/packages) within templates

@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ */
+
+package com.liferay.portal.velocity;
+
+import com.liferay.portal.kernel.log.Log;
+import com.liferay.portal.kernel.log.LogFactoryUtil;
+
+import org.apache.velocity.app.event.MethodExceptionEventHandler;
+
+/**
+ * @author Raymond Augé
+ */
+public class LiferayMethodExceptionEventHandler
+	implements MethodExceptionEventHandler {
+
+	public Object methodException(
+			@SuppressWarnings("rawtypes") Class clazz, String method,
+			Exception e)
+		throws Exception {
+
+		_log.error(e, e);
+
+		return null;
+	}
+
+	private static Log _log = LogFactoryUtil.getLog(
+		LiferayMethodExceptionEventHandler.class);
+
+}
\ No newline at end of file


Move TLS Required check at the end of connect()

It was a *very* bad idea to perform the SecurityMode.Required check in
the connection's reader thread and not at the end of
AbstractXMPPConnectin's connect(). :/

This behavior dates back to 8e750912a765f77a4f178a4f307a8b42c2afb5ae

Fixes SMACK-739

@@ -29,9 +29,7 @@
 import org.jivesoftware.smack.SmackException.NoResponseException;
 import org.jivesoftware.smack.SmackException.NotConnectedException;
 import org.jivesoftware.smack.SmackException.ConnectionException;
-import org.jivesoftware.smack.SmackException.SecurityRequiredByClientException;
 import org.jivesoftware.smack.SmackException.SecurityRequiredByServerException;
-import org.jivesoftware.smack.SmackException.SecurityRequiredException;
 import org.jivesoftware.smack.SynchronizationPoint;
 import org.jivesoftware.smack.XMPPException.StreamErrorException;
 import org.jivesoftware.smack.XMPPConnection;
@@ -917,7 +915,7 @@ protected void setWriter(Writer writer) {
     }

     @Override
-    protected void afterFeaturesReceived() throws SecurityRequiredException, NotConnectedException, InterruptedException {
+    protected void afterFeaturesReceived() throws NotConnectedException, InterruptedException {
         StartTls startTlsFeature = getFeature(StartTls.ELEMENT, StartTls.NAMESPACE);
         if (startTlsFeature != null) {
             if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) {
@@ -929,13 +927,6 @@ protected void afterFeaturesReceived() throws SecurityRequiredException, NotConn
                 sendNonza(new StartTls());
             }
         }
-        // If TLS is required but the server doesn't offer it, disconnect
-        // from the server and throw an error. First check if we've already negotiated TLS
-        // and are secure, however (features get parsed a second time after TLS is established).
-        if (!isSecureConnection() && startTlsFeature == null
-                        && getConfiguration().getSecurityMode() == SecurityMode.required) {
-            throw new SecurityRequiredByClientException();
-        }

         if (getSASLAuthentication().authenticationSuccessful()) {
             // If we have received features after the SASL has been successfully completed, then we


Ensure we secure hawtio-karaf-terminal's /term context

@@ -105,9 +105,7 @@ public void doFilter(final ServletRequest request, final ServletResponse respons
             }
         }

-        boolean doAuthenticate = path.startsWith("/auth") ||
-                path.startsWith("/jolokia") ||
-                path.startsWith("/upload");
+        boolean doAuthenticate = true;

         if (doAuthenticate) {
             LOG.debug("Doing authentication and authorization for path {}", path);
@@ -129,7 +127,7 @@ public void execute(Subject subject) throws Exception {
                     break;
             }
         } else {
-            LOG.debug("No authentication needed for path {}", path);
+            LOG.warn("No authentication needed for path {}", path);
             chain.doFilter(request, response);
         }
     }


[PLXUTILS-161] Commandline shell injection problems

Patch by Charles Duffy, applied unmodified

@@ -16,14 +16,13 @@
  * limitations under the License.
  */

+import junit.framework.TestCase;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.cli.Commandline;

 import java.util.Arrays;
 import java.util.List;

-import junit.framework.TestCase;
-
 public class BourneShellTest
     extends TestCase
 {
@@ -42,7 +41,7 @@ public void testQuoteWorkingDirectoryAndExecutable()

         String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );

-        assertEquals( "/bin/sh -c cd /usr/local/bin && chmod", executable );
+        assertEquals( "/bin/sh -c cd '/usr/local/bin' && 'chmod'", executable );
     }

     public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes()
@@ -54,7 +53,7 @@ public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes()

         String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );

-        assertEquals( "/bin/sh -c cd \"/usr/local/\'something else\'\" && chmod", executable );
+        assertEquals( "/bin/sh -c cd '/usr/local/'\"'\"'something else'\"'\"'' && 'chmod'", executable );
     }

     public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes_BackslashFileSep()
@@ -66,7 +65,7 @@ public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes_Backsl

         String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );

-        assertEquals( "/bin/sh -c cd \"\\usr\\local\\\'something else\'\" && chmod", executable );
+        assertEquals( "/bin/sh -c cd '\\usr\\local\\\'\"'\"'something else'\"'\"'' && 'chmod'", executable );
     }

     public void testPreserveSingleQuotesOnArgument()
@@ -82,7 +81,7 @@ public void testPreserveSingleQuotesOnArgument()

         String cli = StringUtils.join( shellCommandLine.iterator(), " " );
         System.out.println( cli );
-        assertTrue( cli.endsWith( args[0] ) );
+        assertTrue( cli.endsWith("''\"'\"'some arg with spaces'\"'\"''"));
     }

     public void testAddSingleQuotesOnArgumentWithSpaces()
@@ -114,7 +113,7 @@ public void testEscapeSingleQuotesOnArgument()

         String cli = StringUtils.join( shellCommandLine.iterator(), " " );
         System.out.println( cli );
-        assertEquals("cd /usr/bin && chmod 'arg'\\''withquote'", shellCommandLine.get(shellCommandLine.size() - 1));
+        assertEquals("cd '/usr/bin' && 'chmod' 'arg'\"'\"'withquote'", shellCommandLine.get(shellCommandLine.size() - 1));
     }

     public void testArgumentsWithsemicolon()
@@ -146,7 +145,7 @@ public void testArgumentsWithsemicolon()

         assertEquals( "/bin/sh", lines[0] );
         assertEquals( "-c", lines[1] );
-        assertEquals( "chmod --password ';password'", lines[2] );
+        assertEquals( "'chmod' '--password' ';password'", lines[2] );

         commandline = new Commandline( newShell() );
         commandline.setExecutable( "chmod" );
@@ -158,7 +157,7 @@ public void testArgumentsWithsemicolon()

         assertEquals( "/bin/sh", lines[0] );
         assertEquals( "-c", lines[1] );
-        assertEquals( "chmod --password ';password'", lines[2] );
+        assertEquals( "'chmod' '--password' ';password'", lines[2] );

         commandline = new Commandline( new CmdShell() );
         commandline.getShell().setQuotedArgumentsEnabled( true );
@@ -206,7 +205,7 @@ public void testBourneShellQuotingCharacters()

         assertEquals( "/bin/sh", lines[0] );
         assertEquals( "-c", lines[1] );
-        assertEquals( "chmod ' ' '|' '&&' '||' ';' ';;' '&' '()' '<' '<<' '>' '>>' '*' '?' '[' ']' '{' '}' '`'",
+        assertEquals( "'chmod' ' ' '|' '&&' '||' ';' ';;' '&' '()' '<' '<<' '>' '>>' '*' '?' '[' ']' '{' '}' '`'",
                       lines[2] );

     }


Restrict Exception deserialization to Core and JDK classes

when 3rd party exceptions are deserialized they might carry
classes not present on the deserializing node. This causes hard
exceptions and looses the exception entirely. This commit restricts
the classes we support for deserialization for core and selected JDK
classes to guarantee they are present on both source and target nodes

@@ -19,9 +19,15 @@

 package org.elasticsearch.common.io;

+import com.fasterxml.jackson.core.JsonLocation;
+import com.google.common.collect.ImmutableMap;
 import org.elasticsearch.common.Classes;
+import org.elasticsearch.common.collect.IdentityHashSet;
+import org.joda.time.DateTimeFieldType;

 import java.io.*;
+import java.net.*;
+import java.util.*;

 /**
  *
@@ -61,11 +67,11 @@ protected ObjectStreamClass readClassDescriptor()
             case ThrowableObjectOutputStream.TYPE_STACKTRACEELEMENT:
                 return ObjectStreamClass.lookup(StackTraceElement.class);
             case ThrowableObjectOutputStream.TYPE_FAT_DESCRIPTOR:
-                return super.readClassDescriptor();
+                return verify(super.readClassDescriptor());
             case ThrowableObjectOutputStream.TYPE_THIN_DESCRIPTOR:
                 String className = readUTF();
                 Class<?> clazz = loadClass(className);
-                return ObjectStreamClass.lookup(clazz);
+                return verify(ObjectStreamClass.lookup(clazz));
             default:
                 throw new StreamCorruptedException(
                         "Unexpected class descriptor type: " + type);
@@ -96,4 +102,40 @@ protected Class<?> loadClass(String className) throws ClassNotFoundException {
         }
         return clazz;
     }
+
+    private static final Set<Class<?>> CLASS_WHITELIST;
+    private static final Set<Package> PKG_WHITELIST;
+    static {
+        IdentityHashSet<Class<?>> classes = new IdentityHashSet<>();
+        classes.add(String.class);
+        // inet stuff is needed for DiscoveryNode
+        classes.add(Inet6Address.class);
+        classes.add(Inet4Address.class);
+        classes.add(InetAddress.class);
+        classes.add(InetSocketAddress.class);
+        classes.add(SocketAddress.class);
+        classes.add(StackTraceElement.class);
+        classes.add(JsonLocation.class); // JsonParseException uses this
+        IdentityHashSet<Package> packages = new IdentityHashSet<>();
+        packages.add(Integer.class.getPackage()); // java.lang
+        packages.add(List.class.getPackage()); // java.util
+        packages.add(ImmutableMap.class.getPackage()); // com.google.common.collect
+        packages.add(DateTimeFieldType.class.getPackage()); // org.joda.time
+        CLASS_WHITELIST = Collections.unmodifiableSet(classes);
+        PKG_WHITELIST = Collections.unmodifiableSet(packages);
+    }
+
+    private ObjectStreamClass verify(ObjectStreamClass streamClass) throws IOException, ClassNotFoundException {
+        Class<?> aClass = resolveClass(streamClass);
+        Package pkg = aClass.getPackage();
+        if (aClass.isPrimitive() // primitives are fine
+                || aClass.isArray() // arrays are ok too
+                || Throwable.class.isAssignableFrom(aClass)// exceptions are fine
+                || CLASS_WHITELIST.contains(aClass) // whitelist JDK stuff we need
+                || PKG_WHITELIST.contains(aClass.getPackage())
+                || pkg.getName().startsWith("org.elasticsearch")) { // es classes are ok
+            return streamClass;
+        }
+        throw new NotSerializableException(aClass.getName());
+    }
 }


Merge pull request #105 from jenkinsci-cert/SECURITY-304-t3

[SECURITY-304] Encrypt new secrets with CBC and random IV instead of ECB

@@ -0,0 +1,84 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi
+ * Copyright (c) 2016, CloudBees Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package hudson.util;
+
+import com.trilead.ssh2.crypto.Base64;
+import hudson.Util;
+import jenkins.model.Jenkins;
+import jenkins.security.CryptoConfidentialKey;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Historical algorithms for decrypting {@link Secret}s.
+ */
+@Restricted(NoExternalUse.class)
+public class HistoricalSecrets {
+
+    /*package*/ static Secret decrypt(String data, CryptoConfidentialKey key) throws IOException, GeneralSecurityException {
+        byte[] in = Base64.decode(data.toCharArray());
+        Secret s = tryDecrypt(key.decrypt(), in);
+        if (s!=null)    return s;
+
+        // try our historical key for backward compatibility
+        Cipher cipher = Secret.getCipher("AES");
+        cipher.init(Cipher.DECRYPT_MODE, getLegacyKey());
+        return tryDecrypt(cipher, in);
+    }
+
+    /*package*/ static Secret tryDecrypt(Cipher cipher, byte[] in) {
+        try {
+            String plainText = new String(cipher.doFinal(in), UTF_8);
+            if(plainText.endsWith(MAGIC))
+                return new Secret(plainText.substring(0,plainText.length()-MAGIC.length()));
+            return null;
+        } catch (GeneralSecurityException e) {
+            return null; // if the key doesn't match with the bytes, it can result in BadPaddingException
+        }
+    }
+
+    /**
+     * Turns {@link Jenkins#getSecretKey()} into an AES key.
+     *
+     * @deprecated
+     * This is no longer the key we use to encrypt new information, but we still need this
+     * to be able to decrypt what's already persisted.
+     */
+    @Deprecated
+    /*package*/ static SecretKey getLegacyKey() throws GeneralSecurityException {
+        String secret = Secret.SECRET;
+        if(secret==null)    return Jenkins.getInstance().getSecretKeyAsAES128();
+        return Util.toAes128Key(secret);
+    }
+
+    private static final String MAGIC = "::::MAGIC::::";
+}


Merge pull request #107 from jenkinsci-cert/SECURITY-406

[SECURITY-406] Prevent user creation via GET /user/whatever

@@ -2485,11 +2485,11 @@ private File getRootDirFor(String name) {
     /**
      * Gets the user of the given name.
      *
-     * @return the user of the given name (which may or may not be an id), if that person exists or the invoker {@link #hasPermission} on {@link #ADMINISTER}; else null
+     * @return the user of the given name (which may or may not be an id), if that person exists; else null
      * @see User#get(String,boolean), {@link User#getById(String, boolean)}
      */
     public @CheckForNull User getUser(String name) {
-        return User.get(name,hasPermission(ADMINISTER));
+        return User.get(name, User.ALLOW_USER_CREATION_VIA_URL && hasPermission(ADMINISTER));
     }

     public synchronized TopLevelItem createProject( TopLevelItemDescriptor type, String name ) throws IOException {