Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/Tasks.UnitTests/ResourceHandling/GenerateResource_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1940,6 +1940,48 @@ public void InvalidStateFile()
}
}

[Fact]
public void GenerateResourceWarnsWhenUsingBinaryFormatter()
{
using TestEnvironment env = TestEnvironment.Create();
TransientTestFile resource = env.CreateFile(".resx", @"<?xml version=""1.0"" encoding=""utf-8""?>
<root>
<data name=""$this.Icon"" type=""System.Drawing.Icon, System.Drawing"" mimetype=""application/x-microsoft.net.object.binary.base64"">
<value>
AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA
AAD///8BoqKiDaKiotmioqL5oqKiK////wH///8B////Af///wH///8B////AaKioiGioqLxoqKi5aKi
ohn///8B////AbS0tBW0tLTz29vb/7Ozsu18Wi+Be1gswXtYLO17WCzte1gswXtYLIGzs7Lz2dnZ/7S0
tPu0tLQj////Af///wH///8BxsbGQdPT0//Cv739nGs7/6ZsNf+ubzf/rm83/6ZsNf+hdkr/xcTD/8bG
xf/GxsY/////Af///wH///8B////AYxlNmejiGn1r3hE/7uMXv/Ck3H/xJF0/8OPcf+/kGz/uIpd/7SG
Wf+hhWT1jGU2Z////wH///8B////AZZtOzWWbTvVs31G/8KZcf/Yqon/79/P//r28//69fP/79/R/9en
hf++lGz/s31G/5ZtO9WWbTs1////Af///wGhdUGBsIBK/8abb//Zqoj///7r///67v///fL///7y///8
7////ev/2aN6/8KZbP+wgEr/oXVBgf///wH///8BrH5Iwb+PWP/No4H/8NvB///35v/68uP/xcC2//Ht
3v///Oj///Xf/+/Ur//ImXL/v49Y/6x+SMH///8B////AbeHTu3JnGb/z5+A//rz4v/99un/8vDj/42M
hP+Bf3f/0s/C///76//67Mz/x5Bt/8mcZv+3h07t////Af///wHCkFTtzqZx/9Glif/69un//fju////
+f+BgHn/sa6k/4F/d//Jxrr/+vDT/8mWcv/OpnH/wpBU7f///wH///8BzZlbwdOsdf/Zt5j/8ePW//77
9f/19fP/n56V//Dw6f/4+PL/vrmt//Dawv/Sqof/06x1/82ZW8H///8B////AbOddIvTrXf/38Sa/969
qv//////8PDu/+fl2v////f////3///+8//ctJj/28CW/8Kqfv/Gn2qF////AQCZ3T0KmtjZLpzF9d6/
iv/iyaf/37+u//Hj3P/z8ez/9PHr//Hi2f/cuqP/38Oe/4yxqf84ptH5DprWzwCZ3ScAoON9fNHy7WHD
6O86pMb74seS/+bRqf/gwqb/1a6W/9Wrkv/evaD/5M+m/7/Bnv9Hstf9q+P2/Smw6NkAoOMnAKfpe13J
8eW16Pn/Ycfr7zqqzPPsxIj/6cuU/+fQnf/n0J3/6cuU/97Cjv8yqtD1gdPw9XPQ8+sAp+nNAKfpBQCu
7wUAru+LW8v05b/s+v9cy/HpTbLJxfq8dMH6vHTt+rx07fq8dMFRssjDac/y7XzW9u0Aru/JAK7vHf//
/wH///8BALX0AwC19IEAtfTRALX0ywC19Af///8B////Af///wH///8BALX0FwC19NEAtfTJALX0J///
/wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA
//8AAP//AAD//w==
</value>
</data>
</root>
");

GenerateResource gr = Utilities.CreateTask(_output, usePreserialized: true, env: env);
gr.Sources = new ITaskItem[] { new TaskItem(resource.Path) };
gr.WarnOnBinaryFormatterUse = true;

gr.Execute().ShouldBeTrue();

Utilities.AssertLogContainsResource(gr, "GenerateResource.BinaryFormatterUse", "$this.Icon", "System.Drawing.Icon, System.Drawing");
}

/// <summary>
/// Cause failures in ResourceReader
/// </summary>
Expand Down
30 changes: 16 additions & 14 deletions src/Tasks.UnitTests/ResourceHandling/MSBuildResXReader_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void ParsesSingleStringAsString()
@"<data name=""StringResource"" xml:space=""preserve"">
<value>StringValue</value>
<comment>Comment</comment>
</data>"));
</data>"), null, false);

AssertSingleStringResource(resxWithSingleString, "StringResource", "StringValue");
}
Expand All @@ -45,7 +45,7 @@ public void ParsesSingleStringWithoutPreserveAsString()
@"<data name=""StringResource"">
<value> StringValue </value>
<comment>Comment</comment>
</data>"));
</data>"), null, false);

AssertSingleStringResource(resxWithSingleString, "StringResource", " StringValue ");
}
Expand All @@ -58,7 +58,7 @@ public void ParsesSingleWhitespaceStringAsString()
@"<data name=""StringResource"" xml:space=""preserve"">
<value> </value>
<comment>Comment</comment>
</data>"));
</data>"), null, false);

AssertSingleStringResource(resxWithSingleString, "StringResource", " ");
}
Expand All @@ -71,7 +71,7 @@ public void ParsesSingleWhitespaceStringWithNoPreserveAsEmptyString()
@"<data name=""StringResource"">
<value> </value>
<comment>Comment</comment>
</data>"));
</data>"), null, false);

AssertSingleStringResource(resxWithSingleString, "StringResource", "");
}
Expand All @@ -83,7 +83,7 @@ public void ParsesSingleStringWithPartialTypeName()
ResXHelper.SurroundWithBoilerplate(
@"<data name=""StringResource"" type=""System.String"">
<value>StringValue</value>
</data>"));
</data>"), null, false);

AssertSingleStringResource(resxWithSingleString, "StringResource", "StringValue");
}
Expand All @@ -100,7 +100,7 @@ public void LoadsMultipleStringsPreservingOrder()
</data>
<data name=""2StringResource2"" xml:space=""preserve"">
<value>2StringValue2</value>
</data>"));
</data>"), null, false);

resxWithTwoStrings.Count.ShouldBe(2);

Expand All @@ -121,7 +121,7 @@ public void ResXNullRefProducesNullLiveObject()
@" <assembly alias=""System.Windows.Forms"" name=""System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"" />
<data name=""$this.AccessibleDescription"" type=""System.Resources.ResXNullRef, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"">
<value />
</data>"));
</data>"), null, false);

resxWithNullRef.ShouldHaveSingleItem();

Expand All @@ -143,7 +143,7 @@ public void LoadsStringFromFileRefAsString(string stringType)
$@" <assembly alias=""System.Windows.Forms"" name=""System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"" />
<data name=""TextFile1"" type=""System.Resources.ResXFileRef, System.Windows.Forms"">
<value>ResourceHandling\TextFile1.txt;{stringType};utf-8</value>
</data>"));
</data>"), null, false);

AssertSingleStringResource(resxWithLinkedString, "TextFile1", "Contents of TextFile1");
}
Expand Down Expand Up @@ -174,6 +174,8 @@ public void LoadsStringFromFileRefAsStringWithShiftJISEncoding()
<data name=""TextFile1"" type=""System.Resources.ResXFileRef, System.Windows.Forms"">
<value>ResourceHandling\TextFileInShiftJIS.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;shift_jis</value>
</data>"),
null,
false,
Path.Combine(baseDir.Path, nameof(LoadsStringFromFileRefAsStringWithShiftJISEncoding) + ".resx"),
useRelativePath: true);

Expand Down Expand Up @@ -210,7 +212,7 @@ public void PassesThroughBitmapInResx()
b7eblRw4yy8Ta2GCpaZp1sIzz2LfCMS+EYh9401iw/gG1gYfvzjQIXcAAAAASUVORK5CYII=
</value>
</data>
"));
"), null, false);
resxWithEmbeddedBitmap.ShouldHaveSingleItem();
resxWithEmbeddedBitmap[0].ShouldBeOfType(typeof(TypeConverterByteArrayResource));

Expand All @@ -228,7 +230,7 @@ public void TypeConverterStringWellFormatted()
<data name=""color"" type=""System.Drawing.Color, System.Drawing"">
<value>Blue</value>
</data>
"));
"), null, false);
resxWithEmbeddedBitmap.ShouldHaveSingleItem();
resxWithEmbeddedBitmap[0].ShouldBeOfType(typeof(TypeConverterStringResource));

Expand All @@ -252,7 +254,7 @@ public void TypeConverterStringDirectValue()
ResXHelper.SurroundWithBoilerplate(
@" <assembly alias=""System.Drawing"" name=""System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"" />
<data name=""Color1"" type=""System.Drawing.Color, System.Drawing"">Blue</data>
"));
"), null, false);
resxWithEmbeddedBitmap.ShouldHaveSingleItem();
resxWithEmbeddedBitmap[0].ShouldBeOfType(typeof(TypeConverterStringResource));

Expand All @@ -272,7 +274,7 @@ public void ResXFileRefToBitmap()
$@" <data name='Image1' type='System.Resources.ResXFileRef, System.Windows.Forms'>
<value>{bitmapPath};System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
"));
"), null, false);
resxWithLinkedBitmap.ShouldHaveSingleItem();
resxWithLinkedBitmap[0].ShouldBeOfType(typeof(FileStreamResource));

Expand Down Expand Up @@ -301,7 +303,7 @@ public void ResXFileRefToMemoryStream(string typeNameInResx)
$@" <data name='Image1' type='System.Resources.ResXFileRef, System.Windows.Forms'>
<value>{linkedTextFile.Path};{typeNameInResx}</value>
</data>
"));
"), null, false);

var resource = resources.ShouldHaveSingleItem()
.ShouldBeOfType<LiveObjectResource>();
Expand All @@ -321,7 +323,7 @@ public void AssemblyElementWithNoAliasInfersSimpleName()
ResXHelper.SurroundWithBoilerplate(
@" <assembly name=""System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"" />
<data name=""Color1"" type=""System.Drawing.Color, System.Drawing""><value>Blue</value></data>
"));
"), null, false);
resxWithEmbeddedBitmap.ShouldHaveSingleItem();
resxWithEmbeddedBitmap[0].ShouldBeOfType(typeof(TypeConverterStringResource));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void DirtyCleanScenario(bool useMSBuildResXReader)
cache.IsDirty.ShouldBeFalse();

// Getting a file that wasn't in the cache is a write operation.
cache.GetResXFileInfo(resx, useMSBuildResXReader);
cache.GetResXFileInfo(resx, useMSBuildResXReader, null, false);
cache.IsDirty.ShouldBeTrue();

// Add linkedFiles to further test serialization and deserialization.
Expand Down Expand Up @@ -72,7 +72,7 @@ public void DirtyCleanScenario(bool useMSBuildResXReader)
resX2.linkedFiles[1].ShouldBe(resX.linkedFiles[1]);

// Asking for a file that's in the cache should not dirty the cache.
cache2.GetResXFileInfo(resx, useMSBuildResXReader);
cache2.GetResXFileInfo(resx, useMSBuildResXReader, null, false);
cache2.IsDirty.ShouldBeFalse();

// Changing UseSourcePath to false should dirty the cache.
Expand Down
21 changes: 16 additions & 5 deletions src/Tasks/GenerateResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@ public string StronglyTypedLanguage
}
}

// Indicates whether any BinaryFormatter use should lead to a warning.
public bool WarnOnBinaryFormatterUse
{
get; set;
}

/// <summary>
/// Specifies the namespace to use for the generated class source for the
/// strongly typed resource. If left blank, no namespace is used.
Expand Down Expand Up @@ -808,7 +814,8 @@ public override bool Execute()
StronglyTypedClassName,
PublicClass,
ExtractResWFiles,
OutputDirectory);
OutputDirectory,
WarnOnBinaryFormatterUse);

this.StronglyTypedClassName = process.StronglyTypedClassName; // in case a default was chosen
this.StronglyTypedFileName = process.StronglyTypedFilename; // in case a default was chosen
Expand Down Expand Up @@ -1510,7 +1517,7 @@ private bool ShouldRebuildResgenOutputFile(string sourceFilePath, string outputF
ResGenDependencies.ResXFile resxFileInfo;
try
{
resxFileInfo = _cache.GetResXFileInfo(sourceFilePath, UsePreserializedResources);
resxFileInfo = _cache.GetResXFileInfo(sourceFilePath, UsePreserializedResources, Log, WarnOnBinaryFormatterUse);
}
catch (Exception e) when (!ExceptionHandling.NotExpectedIoOrXmlException(e) || e is MSBuildResXException)
{
Expand Down Expand Up @@ -1971,7 +1978,7 @@ private bool DetermineWhetherSerializedObjectLoads(string data)
{
byte[] serializedData = ByteArrayFromBase64WrappedString(data);

BinaryFormatter binaryFormatter = new BinaryFormatter();
BinaryFormatter binaryFormatter = new();

using (MemoryStream memoryStream = new MemoryStream(serializedData))
{
Expand Down Expand Up @@ -2337,6 +2344,8 @@ internal bool StronglyTypedResourceSuccessfullyCreated
/// </summary>
private bool _useSourcePath = false;

private bool _logWarningForBinaryFormatter = false;

#endregion

/// <summary>
Expand All @@ -2357,7 +2366,8 @@ internal void Run(
string classname,
bool publicClass,
bool extractingResWFiles,
string resWOutputDirectory)
string resWOutputDirectory,
bool logWarningForBinaryFormatter)
{
_logger = log;
_assemblyFiles = assemblyFilesList;
Expand All @@ -2376,6 +2386,7 @@ internal void Run(
_resWOutputDirectory = resWOutputDirectory;
_portableLibraryCacheInfo = new List<ResGenDependencies.PortableLibraryFile>();
_usePreserializedResources = usePreserializedResources;
_logWarningForBinaryFormatter = logWarningForBinaryFormatter;

#if !FEATURE_ASSEMBLYLOADCONTEXT
// If references were passed in, we will have to give the ResxResourceReader an object
Expand Down Expand Up @@ -2980,7 +2991,7 @@ private void ReadResources(String filename, bool shouldUseSourcePath, String out
}
else
{
foreach (IResource resource in MSBuildResXReader.GetResourcesFromFile(filename, shouldUseSourcePath))
foreach (IResource resource in MSBuildResXReader.GetResourcesFromFile(filename, shouldUseSourcePath, _logger, _logWarningForBinaryFormatter))
{
AddResource(reader, resource, filename, 0, 0);
}
Expand Down
4 changes: 3 additions & 1 deletion src/Tasks/Microsoft.Common.CurrentVersion.targets
Original file line number Diff line number Diff line change
Expand Up @@ -3328,8 +3328,10 @@ Copyright (C) Microsoft Corporation. All rights reserved.
SdkToolsPath="$(ResgenToolPath)"
ExecuteAsTool="$(ResGenExecuteAsTool)"
EnvironmentVariables="$(ResGenEnvironment)"
WarnOnBinaryFormatterUse="$(GenerateResourceWarnOnBinaryFormatterUse)"
MSBuildRuntime="$(GenerateResourceMSBuildRuntime)"
MSBuildArchitecture="$(GenerateResourceMSBuildArchitecture)">
MSBuildArchitecture="$(GenerateResourceMSBuildArchitecture)"
>

<Output TaskParameter="FilesWritten" ItemName="FileWrites"/>
<Output TaskParameter="StronglyTypedFileName" ItemName="Compile"/>
Expand Down
18 changes: 9 additions & 9 deletions src/Tasks/ResGenDependencies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ public override void Translate(ITranslator translator)
translator.Translate(ref baseLinkedFileDirectory);
}

internal ResXFile GetResXFileInfo(string resxFile, bool useMSBuildResXReader)
internal ResXFile GetResXFileInfo(string resxFile, bool useMSBuildResXReader, TaskLoggingHelper log, bool logWarningForBinaryFormatter)
{
// First, try to retrieve the resx information from our hashtable.
if (!resXFiles.TryGetValue(resxFile, out ResXFile retVal))
{
// Ok, the file wasn't there. Add it to our cache and return it to the caller.
retVal = AddResxFile(resxFile, useMSBuildResXReader);
retVal = AddResxFile(resxFile, useMSBuildResXReader, log, logWarningForBinaryFormatter);
}
else
{
Expand All @@ -141,19 +141,19 @@ internal ResXFile GetResXFileInfo(string resxFile, bool useMSBuildResXReader)
{
resXFiles.Remove(resxFile);
_isDirty = true;
retVal = AddResxFile(resxFile, useMSBuildResXReader);
retVal = AddResxFile(resxFile, useMSBuildResXReader, log, logWarningForBinaryFormatter);
}
}

return retVal;
}

private ResXFile AddResxFile(string file, bool useMSBuildResXReader)
private ResXFile AddResxFile(string file, bool useMSBuildResXReader, TaskLoggingHelper log, bool logWarningForBinaryFormatter)
{
// This method adds a .resx file "file" to our .resx cache. The method causes the file
// to be cracked for contained files.

var resxFile = new ResXFile(file, BaseLinkedFileDirectory, useMSBuildResXReader);
var resxFile = new ResXFile(file, BaseLinkedFileDirectory, useMSBuildResXReader, log, logWarningForBinaryFormatter);
resXFiles.Add(file, resxFile);
_isDirty = true;
return resxFile;
Expand Down Expand Up @@ -230,7 +230,7 @@ internal sealed class ResXFile : DependencyFile, ITranslatable

internal string[] LinkedFiles => linkedFiles;

internal ResXFile(string filename, string baseLinkedFileDirectory, bool useMSBuildResXReader) : base(filename)
internal ResXFile(string filename, string baseLinkedFileDirectory, bool useMSBuildResXReader, TaskLoggingHelper log, bool logWarningForBinaryFormatter) : base(filename)
{
// Creates a new ResXFile object and populates the class member variables
// by computing a list of linked files within the .resx that was passed in.
Expand All @@ -239,7 +239,7 @@ internal ResXFile(string filename, string baseLinkedFileDirectory, bool useMSBui

if (FileSystems.Default.FileExists(FileName))
{
linkedFiles = GetLinkedFiles(filename, baseLinkedFileDirectory, useMSBuildResXReader);
linkedFiles = GetLinkedFiles(filename, baseLinkedFileDirectory, useMSBuildResXReader, log, logWarningForBinaryFormatter);
}
}

Expand All @@ -260,7 +260,7 @@ public void Translate(ITranslator translator)
/// </summary>
/// <exception cref="ArgumentException">May be thrown if Resx is invalid. May contain XmlException.</exception>
/// <exception cref="XmlException">May be thrown if Resx is invalid</exception>
private static string[] GetLinkedFiles(string filename, string baseLinkedFileDirectory, bool useMSBuildResXReader)
private static string[] GetLinkedFiles(string filename, string baseLinkedFileDirectory, bool useMSBuildResXReader, TaskLoggingHelper log, bool logWarningForBinaryFormatter)
{
// This method finds all linked .resx files for the .resx file that is passed in.
// filename is the filename of the .resx file that is to be examined.
Expand All @@ -270,7 +270,7 @@ private static string[] GetLinkedFiles(string filename, string baseLinkedFileDir

if (useMSBuildResXReader)
{
foreach (IResource resource in MSBuildResXReader.GetResourcesFromFile(filename, pathsRelativeToBasePath: baseLinkedFileDirectory == null))
foreach (IResource resource in MSBuildResXReader.GetResourcesFromFile(filename, pathsRelativeToBasePath: baseLinkedFileDirectory == null, log, logWarningForBinaryFormatter))
{
if (resource is FileStreamResource linkedResource)
{
Expand Down
Loading