Kaynağa Gözat

Date missing cross-site marshalling

A lot of Date methods (the family of to???String) miss cross-site
marshalling. This change fixes that by removing
`DateImplementation::m_scriptContext` and pass in `requestContext`
everywhere.
Jianchun Xu 9 yıl önce
ebeveyn
işleme
ef8206a2c6

+ 1 - 2
lib/Runtime/Language/JavascriptConversion.cpp

@@ -415,8 +415,7 @@ CommonNumber:
                         // if IsES6ToPrimitiveEnabled flag is off we also fall back to OrdinaryToPrimitive
                         return MethodCallToPrimitive(aValue, hint, requestContext);
                     }
-                    //NOTE: Consider passing requestContext to JavascriptDate::ToString
-                    return CrossSite::MarshalVar(requestContext, JavascriptDate::ToString(dateObject));
+                    return JavascriptDate::ToString(dateObject, requestContext);
                 }
             }
 

+ 29 - 28
lib/Runtime/Library/DateImplementation.cpp

@@ -119,7 +119,7 @@ namespace Js {
     ///----------------------------------------------------------------------------
     ///----------------------------------------------------------------------------
 
-    DateImplementation::DateImplementation(double value, ScriptContext* scriptContext)
+    DateImplementation::DateImplementation(double value)
     {
         // Assume DateImplementation is allocated in the recycler and is zero initialized
         // Do not stack allocate of this struct, as it doesn't initialize all fields.
@@ -129,7 +129,6 @@ namespace Js {
         Assert(!ThreadContext::IsOnStack(this));
         AssertValue<byte>(this, 0, sizeof(DateImplementation));
 
-        m_scriptContext = scriptContext;
         m_modified = false;
 
         SetTvUtc(value);
@@ -155,82 +154,83 @@ namespace Js {
     }
 
     JavascriptString*
-    DateImplementation::GetString(DateStringFormat dsf, DateTimeFlag noDateTime)
+    DateImplementation::GetString(DateStringFormat dsf,
+        ScriptContext* requestContext, DateTimeFlag noDateTime)
     {
         if (JavascriptNumber::IsNan(m_tvUtc))
         {
-            return m_scriptContext->GetLibrary()->GetInvalidDateString();
+            return requestContext->GetLibrary()->GetInvalidDateString();
         }
 
         switch (dsf)
          {
             default:
-                EnsureYmdLcl();
-                return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext);
+                EnsureYmdLcl(requestContext);
+                return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext);
 
 #ifdef ENABLE_GLOBALIZATION
             case DateStringFormat::Locale:
-                EnsureYmdLcl();
+                EnsureYmdLcl(requestContext);
 
                 if( m_ymdLcl.year > 1600 && m_ymdLcl.year < 10000 )
                 {
                     // The year falls in the range which can be handled by both the Win32
                     // function GetDateFormat and the COM+ date type
                     // - the latter is for forward compatibility with JS 7.
-                    JavascriptString *bs = GetDateLocaleString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext);
+                    JavascriptString *bs = GetDateLocaleString(&m_ymdLcl, &m_tzd, noDateTime, requestContext);
                     if (bs != nullptr)
                     {
                         return bs;
                     }
                     else
                     {
-                        return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext);
+                        return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext);
                     }
                 }
                 else
                 {
-                    return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext);
+                    return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext);
                 }
 #endif
 
             case DateStringFormat::GMT:
                 EnsureYmdUtc();
-                return GetDateGmtString(&m_ymdUtc, m_scriptContext);
+                return GetDateGmtString(&m_ymdUtc, requestContext);
         }
     }
 
     JavascriptString*
-    DateImplementation::GetISOString()
+    DateImplementation::GetISOString(ScriptContext* requestContext)
     {
         // ES5 15.9.5.43: throw RangeError if time value is not a finite number
         if (!Js::NumberUtilities::IsFinite(m_tvUtc))
         {
-            JavascriptError::ThrowRangeError(m_scriptContext, JSERR_NeedNumber);
+            JavascriptError::ThrowRangeError(requestContext, JSERR_NeedNumber);
         }
 
-        CompoundString *const bs = CompoundString::NewWithCharCapacity(30, m_scriptContext->GetLibrary());
+        CompoundString *const bs = CompoundString::NewWithCharCapacity(30, requestContext->GetLibrary());
 
-        GetDateComponent(bs, DateData::FullYear, 0);
+        GetDateComponent(bs, DateData::FullYear, 0, requestContext);
         bs->AppendChars(_u('-'));
         // month
-        GetDateComponent(bs, DateData::Month, 1/*adjustment*/);
+        GetDateComponent(bs, DateData::Month, 1/*adjustment*/, requestContext);
         bs->AppendChars(_u('-'));
         // date
-        GetDateComponent(bs, DateData::Date, 0);
+        GetDateComponent(bs, DateData::Date, 0, requestContext);
         bs->AppendChars(_u('T'));
         // hours
-        GetDateComponent(bs, DateData::Hours, 0);
+        GetDateComponent(bs, DateData::Hours, 0, requestContext);
         bs->AppendChars(_u(':'));
         // minutes
-        GetDateComponent(bs, DateData::Minutes, 0);
+        GetDateComponent(bs, DateData::Minutes, 0, requestContext);
         bs->AppendChars(_u(':'));
         // seconds
-        GetDateComponent(bs, DateData::Seconds, 0);
+        GetDateComponent(bs, DateData::Seconds, 0, requestContext);
 
         // ES5 fill in milliseconds but v5.8 does not
         bs->AppendChars(_u('.'));
         // milliseconds
-        GetDateComponent(bs, DateData::Milliseconds, 0);
+        GetDateComponent(bs, DateData::Milliseconds, 0, requestContext);
 
         bs->AppendChars(_u('Z'));
 
@@ -238,9 +238,10 @@ namespace Js {
     }
 
     void
-    DateImplementation::GetDateComponent(CompoundString *bs, DateData componentType, int adjust)
+    DateImplementation::GetDateComponent(CompoundString *bs, DateData componentType, int adjust,
+        ScriptContext* requestContext)
     {
-        double value = this->GetDateData(componentType, true /* fUTC */, m_scriptContext);
+        double value = this->GetDateData(componentType, true /* fUTC */, requestContext);
         if(Js::NumberUtilities::IsFinite(value))
         {
             const int ival = (int)value + adjust;
@@ -339,10 +340,10 @@ namespace Js {
     ///----------------------------------------------------------------------------
 
     void
-    DateImplementation::SetTvLcl(double tv)
+    DateImplementation::SetTvLcl(double tv, ScriptContext* requestContext)
     {
         m_grfval = 0;
-        m_tvUtc  = GetTvUtc(tv, m_scriptContext);
+        m_tvUtc  = GetTvUtc(tv, requestContext);
     }
 
     JavascriptString*
@@ -580,7 +581,7 @@ Error:
         }
         else
         {
-            EnsureYmdLcl();
+            EnsureYmdLcl(scriptContext);
             pymd = &m_ymdLcl;
         }
 
@@ -1709,7 +1710,7 @@ LError:
             }
             else
             {
-                EnsureYmdLcl();
+                EnsureYmdLcl(scriptContext);
                 pymd = &m_ymdLcl;
                 tv = m_tvLcl;
             }
@@ -1782,7 +1783,7 @@ LError:
         }
         else
         {
-            SetTvLcl(tv);
+            SetTvLcl(tv, scriptContext);
         }
 
         m_modified = true;

+ 34 - 43
lib/Runtime/Library/DateImplementation.h

@@ -30,7 +30,7 @@ namespace Js {
         static double DoubleToTvUtc(double tv);
     private:
         DateImplementation(VirtualTableInfoCtorEnum) { m_modified = false; }
-        DateImplementation(double value, ScriptContext* scriptContext);
+        DateImplementation(double value);
 
         BEGIN_ENUM_BYTE(DateStringFormat)
             Default,
@@ -103,12 +103,14 @@ namespace Js {
         void ClearModified() { m_modified = false; }
 
     private:
-        JavascriptString* GetString(DateStringFormat dsf, DateTimeFlag noDateTime = DateTimeFlag::None);
+        JavascriptString* GetString(DateStringFormat dsf, ScriptContext* requestContext,
+            DateTimeFlag noDateTime = DateTimeFlag::None);
 
-        JavascriptString* GetISOString();
-        void GetDateComponent(CompoundString *bs, DateData componentType, int adjust);
+        JavascriptString* GetISOString(ScriptContext* requestContext);
+        void GetDateComponent(CompoundString *bs, DateData componentType, int adjust,
+            ScriptContext* requestContext);
 
-        void SetTvLcl(double tv);
+        void SetTvLcl(double tv, ScriptContext* requestContext);
 
         double GetDateData(DateData dd, bool fUtc, ScriptContext* scriptContext);
         double SetDateData(Arguments args, DateData dd, bool fUtc, ScriptContext* scriptContext);
@@ -175,11 +177,6 @@ namespace Js {
             }
         }
 
-        inline void EnsureTvLcl(void)
-        {
-            EnsureTvLcl(m_scriptContext);
-        }
-
         ///------------------------------------------------------------------------------
         /// Make sure m_ymdLcl is valid. (Shared with hybrid debugging, which may use a fake scriptContext.)
         ///------------------------------------------------------------------------------
@@ -195,11 +192,6 @@ namespace Js {
             m_grfval |= DateValueType::YearMonthDayLocal;
         }
 
-        inline void EnsureYmdLcl(void)
-        {
-            EnsureYmdLcl(m_scriptContext);
-        }
-
         ///------------------------------------------------------------------------------
         /// Make sure m_ymdUtc is valid.
         ///------------------------------------------------------------------------------
@@ -214,61 +206,61 @@ namespace Js {
         }
 
 
-        inline Var GetFullYear()
+        inline Var GetFullYear(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
-            return JavascriptNumber::ToVar(m_ymdLcl.year, m_scriptContext);
+            EnsureYmdLcl(requestContext);
+            return JavascriptNumber::ToVar(m_ymdLcl.year, requestContext);
         }
 
-        inline Var GetYear()
+        inline Var GetYear(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
+            EnsureYmdLcl(requestContext);
             // WOOB bug 1099381: ES5 spec B.2.4: getYear() must return YearFromTime() - 1900.
             // Note that negative value is OK for the spec.
             int value = m_ymdLcl.year - 1900;
-            return JavascriptNumber::ToVar(value, m_scriptContext);
+            return JavascriptNumber::ToVar(value, requestContext);
         }
 
-        inline Var GetMonth()
+        inline Var GetMonth(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
-            return JavascriptNumber::ToVar(m_ymdLcl.mon, m_scriptContext);
+            EnsureYmdLcl(requestContext);
+            return JavascriptNumber::ToVar(m_ymdLcl.mon, requestContext);
         }
 
-        inline Var GetDate()
+        inline Var GetDate(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
-            return JavascriptNumber::ToVar(m_ymdLcl.mday + 1, m_scriptContext);
+            EnsureYmdLcl(requestContext);
+            return JavascriptNumber::ToVar(m_ymdLcl.mday + 1, requestContext);
         }
 
-        inline Var GetDay()
+        inline Var GetDay(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
-            return JavascriptNumber::ToVar(m_ymdLcl.wday, m_scriptContext);
+            EnsureYmdLcl(requestContext);
+            return JavascriptNumber::ToVar(m_ymdLcl.wday, requestContext);
         }
 
-        inline Var GetHours()
+        inline Var GetHours(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
-            return JavascriptNumber::ToVar((m_ymdLcl.time / 3600000)%24, m_scriptContext);
+            EnsureYmdLcl(requestContext);
+            return JavascriptNumber::ToVar((m_ymdLcl.time / 3600000)%24, requestContext);
         }
 
-        inline Var GetMinutes()
+        inline Var GetMinutes(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
-            return JavascriptNumber::ToVar((m_ymdLcl.time / 60000) % 60, m_scriptContext);
+            EnsureYmdLcl(requestContext);
+            return JavascriptNumber::ToVar((m_ymdLcl.time / 60000) % 60, requestContext);
         }
 
-        inline Var GetSeconds()
+        inline Var GetSeconds(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
-            return JavascriptNumber::ToVar((m_ymdLcl.time / 1000) % 60, m_scriptContext);
+            EnsureYmdLcl(requestContext);
+            return JavascriptNumber::ToVar((m_ymdLcl.time / 1000) % 60, requestContext);
         }
 
-        inline Var GetDateMilliSeconds()
+        inline Var GetDateMilliSeconds(ScriptContext* requestContext)
         {
-            EnsureYmdLcl();
-            return JavascriptNumber::ToVar(m_ymdLcl.time % 1000, m_scriptContext);
+            EnsureYmdLcl(requestContext);
+            return JavascriptNumber::ToVar(m_ymdLcl.time % 1000, requestContext);
         }
 
         template <class StringBuilder, class ScriptContext, class NewStringBuilderFunc>
@@ -287,7 +279,6 @@ namespace Js {
         FieldNoBarrier(DateTime::YMD)   m_ymdLcl;
         Field(TZD)                      m_tzd;
         Field(uint32)                   m_grfval; // Which fields are valid. m_tvUtc is always valid.
-        FieldNoBarrier(ScriptContext *) m_scriptContext;
         Field(bool)                     m_modified : 1; // Whether SetDateData was called on this class
 
         friend JavascriptDate;

+ 29 - 26
lib/Runtime/Library/JavascriptDate.cpp

@@ -12,13 +12,13 @@
 namespace Js
 {
     JavascriptDate::JavascriptDate(double value, DynamicType * type)
-        : DynamicObject(type), m_date(value, type->GetScriptContext())
+        : DynamicObject(type), m_date(value)
     {
         Assert(IsDateTypeId(type->GetTypeId()));
     }
 
     JavascriptDate::JavascriptDate(DynamicType * type)
-        : DynamicObject(type), m_date(0, type->GetScriptContext())
+        : DynamicObject(type), m_date(0)
     {
         Assert(type->GetTypeId() == TypeIds_Date);
     }
@@ -88,7 +88,7 @@ namespace Js
 
             // ES5 15.9.2.1: Date() should returns a string exactly the same as (new Date().toString()).
             JavascriptDate* pDate = NewInstanceAsConstructor(args, scriptContext, /* forceCurrentDate */ true);
-            JavascriptString* res = JavascriptDate::ToString(pDate);
+            JavascriptString* res = JavascriptDate::ToString(pDate, scriptContext);
 
 #if ENABLE_TTD
             if(scriptContext->ShouldPerformReplayAction())
@@ -228,7 +228,7 @@ namespace Js
             values[3] * 3600000 + values[4] * 60000 + values[5] * 1000 + values[6]);
 
         // Set the time.
-        pDate->m_date.SetTvLcl(timeValue);
+        pDate->m_date.SetTvLcl(timeValue, scriptContext);
 
         return pDate;
     }
@@ -298,7 +298,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetDate();
+            return date->m_date.GetDate(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -325,7 +325,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetDay();
+            return date->m_date.GetDay(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -352,7 +352,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetFullYear();
+            return date->m_date.GetFullYear(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -379,7 +379,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetYear();
+            return date->m_date.GetYear(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -406,7 +406,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetHours();
+            return date->m_date.GetHours(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -433,7 +433,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetDateMilliSeconds();
+            return date->m_date.GetDateMilliSeconds(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -460,7 +460,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetMinutes();
+            return date->m_date.GetMinutes(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -487,7 +487,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetMonth();
+            return date->m_date.GetMonth(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -514,7 +514,7 @@ namespace Js
 
         if (!date->m_date.IsNaN())
         {
-            return date->m_date.GetSeconds();
+            return date->m_date.GetSeconds(scriptContext);
         }
         return scriptContext->GetLibrary()->GetNaN();
     }
@@ -1247,7 +1247,7 @@ namespace Js
 
         AssertMsg(args.Info.Count > 0, "Negative argument count");
         return date->m_date.GetString(
-            DateImplementation::DateStringFormat::Default,
+            DateImplementation::DateStringFormat::Default, scriptContext,
             DateImplementation::DateTimeFlag::NoTime);
     }
 
@@ -1273,7 +1273,7 @@ namespace Js
         JavascriptDate* date = JavascriptDate::FromVar(args[0]);
 
         AssertMsg(args.Info.Count > 0, "Negative argument count");
-        return date->m_date.GetISOString();
+        return date->m_date.GetISOString(scriptContext);
     }
 
     Var JavascriptDate::EntryToJSON(RecyclableObject* function, CallInfo callInfo, ...)
@@ -1363,7 +1363,7 @@ namespace Js
 
         AssertMsg(args.Info.Count > 0, "Negative argument count");
         return date->m_date.GetString(
-            DateImplementation::DateStringFormat::Locale,
+            DateImplementation::DateStringFormat::Locale, scriptContext,
             DateImplementation::DateTimeFlag::NoTime);
     }
 
@@ -1411,18 +1411,20 @@ namespace Js
 #endif
 
         AssertMsg(args.Info.Count > 0, "Negative argument count");
-        return JavascriptDate::ToLocaleString(date);
+        return JavascriptDate::ToLocaleString(date, scriptContext);
     }
 
-    JavascriptString* JavascriptDate::ToLocaleString(JavascriptDate* date)
+    JavascriptString* JavascriptDate::ToLocaleString(JavascriptDate* date,
+        ScriptContext* requestContext)
     {
-        return date->m_date.GetString(DateImplementation::DateStringFormat::Locale);
+        return date->m_date.GetString(DateImplementation::DateStringFormat::Locale, requestContext);
     }
 
-    JavascriptString* JavascriptDate::ToString(JavascriptDate* date)
+    JavascriptString* JavascriptDate::ToString(JavascriptDate* date,
+        ScriptContext* requestContext)
     {
         Assert(date);
-        return date->m_date.GetString(DateImplementation::DateStringFormat::Default);
+        return date->m_date.GetString(DateImplementation::DateStringFormat::Default, requestContext);
     }
 
     Var JavascriptDate::EntryToLocaleTimeString(RecyclableObject* function, CallInfo callInfo, ...)
@@ -1470,7 +1472,7 @@ namespace Js
 
         AssertMsg(args.Info.Count > 0, "Negative argument count");
         return date->m_date.GetString(
-            DateImplementation::DateStringFormat::Locale,
+            DateImplementation::DateStringFormat::Locale, scriptContext,
             DateImplementation::DateTimeFlag::NoDate);
     }
 
@@ -1497,7 +1499,7 @@ namespace Js
 
         AssertMsg(args.Info.Count > 0, "Negative argument count");
         return date->m_date.GetString(
-            DateImplementation::DateStringFormat::Default,
+            DateImplementation::DateStringFormat::Default, scriptContext,
             DateImplementation::DateTimeFlag::NoDate);
     }
 
@@ -1533,7 +1535,7 @@ namespace Js
 
         AssertMsg(args.Info.Count > 0, "Negative argument count");
         return date->m_date.GetString(
-            DateImplementation::DateStringFormat::GMT,
+            DateImplementation::DateStringFormat::GMT, scriptContext,
             DateImplementation::DateTimeFlag::None);
     }
 
@@ -1583,7 +1585,7 @@ namespace Js
         JavascriptDate* date = JavascriptDate::FromVar(args[0]);
 
         AssertMsg(args.Info.Count > 0, "Negative argument count");
-        return JavascriptDate::ToString(date);
+        return JavascriptDate::ToString(date, scriptContext);
     }
 
     BOOL JavascriptDate::TryInvokeRemotely(JavascriptMethod entryPoint, ScriptContext * scriptContext, Arguments & args, Var * result)
@@ -1628,7 +1630,8 @@ namespace Js
     BOOL JavascriptDate::GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext)
     {
         ENTER_PINNED_SCOPE(JavascriptString, valueStr);
-        valueStr = this->m_date.GetString(DateImplementation::DateStringFormat::Default);
+        valueStr = this->m_date.GetString(
+            DateImplementation::DateStringFormat::Default, requestContext);
         stringBuilder->Append(valueStr->GetString(), valueStr->GetLength());
         LEAVE_PINNED_SCOPE();
         return TRUE;

+ 2 - 2
lib/Runtime/Library/JavascriptDate.h

@@ -132,8 +132,8 @@ namespace Js
         static Var EntryValueOf(RecyclableObject* function, CallInfo callInfo, ...);
         static Var EntrySymbolToPrimitive(RecyclableObject* function, CallInfo callInfo, ...);
 
-        static JavascriptString* ToLocaleString(JavascriptDate* date);
-        static JavascriptString* ToString(JavascriptDate* date);
+        static JavascriptString* ToLocaleString(JavascriptDate* date, ScriptContext* requestContext);
+        static JavascriptString* ToString(JavascriptDate* date, ScriptContext* requestContext);
 
         virtual BOOL ToPrimitive(JavascriptHint hint, Var* result, ScriptContext * requestContext) override;
         virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;

+ 19 - 0
test/Date/marshalbug.js

@@ -0,0 +1,19 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+const crossSiteDate =
+    WScript.LoadScript("var x = new Date()", "samethread").x;
+
+// Run every Date method on the cross-site instance
+Object.getOwnPropertyNames(Date.prototype)
+    .filter(name => !name.match(/^set/))
+    .forEach(name => {
+        print(name);
+        try {
+            print(Date.prototype[name].call(crossSiteDate));
+        } catch(e) {
+            // Ignore. Just to catch assertions on debug build.
+        }
+    });

+ 9 - 0
test/Date/rlexe.xml

@@ -108,4 +108,13 @@
       </override>
     </condition>
   </test>
+  <test>
+    <default>
+      <files>marshalbug.js</files>
+      <!-- only to catch debug build assertions -->
+      <compile-flags>-nonative -intl-</compile-flags>
+      <baseline/>
+      <tags>exclude_fre,exclude_dynapogo</tags>
+    </default>
+  </test>
 </regress-exe>