Skip to content

Commit

Permalink
Update runtimeconfig.json and deps.json paths when these break past t…
Browse files Browse the repository at this point in the history
…he MAX_PATH threshold (#56224)

* Update runtimeconfig paths if we exceed MAX_PATH

* Add test

* PR feedback

* Get apphost for all platforms

* Probe bundle first
Fix return value of realpath

* Check for empty path upfront
  • Loading branch information
mateoatr committed Jul 27, 2021
1 parent 2a02896 commit 866808d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,37 @@ public void AppHost_FrameworkDependent_GlobalLocation_Succeeds(bool useRegistere
}
}

[Fact]
public void RuntimeConfig_FilePath_Breaks_MAX_PATH_Threshold()
{
var project = sharedTestState.PortableAppFixture_Published
.Copy();

var appExeName = Path.GetFileName(project.TestProject.AppExe);
var outputDir = project.TestProject.OutputDirectory;

// Move the portable app to a path such that the length of the executable's fullpath
// is just 1 char behind MAX_PATH (260) so that the runtimeconfig(.dev).json files
// break this threshold. This will cause hostfxr to normalize these paths -- here we
// are checking that the updated paths are used.
var tmp = Path.GetTempPath();
var dirName = new string('a', 259 - tmp.Length - appExeName.Length - 1);
var newDir = Path.Combine(tmp, dirName);
var appExe = Path.Combine(newDir, appExeName);
Debug.Assert(appExe.Length == 259);
Directory.CreateDirectory(newDir);
foreach (var file in Directory.GetFiles(outputDir, "*.*", SearchOption.TopDirectoryOnly))
File.Copy(file, Path.Combine(newDir, Path.GetFileName(file)), true);

Command.Create(appExe)
.DotNetRoot(project.BuiltDotnet.BinPath)
.EnableTracingAndCaptureOutputs()
.MultilevelLookup(false)
.Execute()
.Should().Pass()
.And.HaveStdOutContaining("Hello World");
}

[Fact]
public void ComputedTPADoesntEndWithPathSeparator()
{
Expand Down Expand Up @@ -707,7 +738,7 @@ public SharedTestState()

PortableAppFixture_Published = new TestProjectFixture("PortableApp", RepoDirectories)
.EnsureRestored()
.PublishProject();
.PublishProject(extraArgs: "/p:UseAppHost=true");

MockApp = new TestApp(SharedFramework.CalculateUniqueTestDirectory(Path.Combine(TestArtifact.TestArtifactsPath, "portableAppActivation")), "App");
Directory.CreateDirectory(MockApp.Location);
Expand Down
4 changes: 2 additions & 2 deletions src/native/corehost/deps_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ bool deps_json_t::has_package(const pal::string_t& name, const pal::string_t& ve
bool deps_json_t::load(bool is_framework_dependent, const pal::string_t& deps_path, const rid_fallback_graph_t& rid_fallback_graph)
{
m_deps_file = deps_path;
m_file_exists = bundle::info_t::config_t::probe(deps_path) || pal::file_exists(deps_path);
m_file_exists = bundle::info_t::config_t::probe(deps_path) || pal::realpath(&m_deps_file, true);

json_parser_t json;
if (!m_file_exists)
Expand All @@ -449,7 +449,7 @@ bool deps_json_t::load(bool is_framework_dependent, const pal::string_t& deps_pa
return true;
}

if (!json.parse_file(deps_path))
if (!json.parse_file(m_deps_file))
{
return false;
}
Expand Down
13 changes: 6 additions & 7 deletions src/native/corehost/hostmisc/pal.windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,11 +645,15 @@ bool pal::clr_palstring(const char* cstr, pal::string_t* out)
// Return if path is valid and file exists, return true and adjust path as appropriate.
bool pal::realpath(string_t* path, bool skip_error_logging)
{
if (path->empty())
{
return false;
}

if (LongFile::IsNormalized(*path))
{
WIN32_FILE_ATTRIBUTE_DATA data;
if (path->empty() // An empty path doesn't exist
|| GetFileAttributesExW(path->c_str(), GetFileExInfoStandard, &data) != 0)
if (GetFileAttributesExW(path->c_str(), GetFileExInfoStandard, &data) != 0)
{
return true;
}
Expand Down Expand Up @@ -713,11 +717,6 @@ bool pal::realpath(string_t* path, bool skip_error_logging)

bool pal::file_exists(const string_t& path)
{
if (path.empty())
{
return false;
}

string_t tmp(path);
return pal::realpath(&tmp, true);
}
Expand Down
6 changes: 3 additions & 3 deletions src/native/corehost/runtime_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,9 @@ bool runtime_config_t::ensure_dev_config_parsed()
trace::verbose(_X("Attempting to read dev runtime config: %s"), m_dev_path.c_str());

pal::string_t retval;
if (!pal::file_exists(m_dev_path))
if (!pal::realpath(&m_dev_path, true))
{
// Not existing is valid.
// It is valid for the runtimeconfig.dev.json to not exist.
return true;
}

Expand Down Expand Up @@ -402,7 +402,7 @@ bool runtime_config_t::ensure_parsed()
trace::verbose(_X("Did not successfully parse the runtimeconfig.dev.json"));
}

if (!bundle::info_t::config_t::probe(m_path) && !pal::file_exists(m_path))
if (!bundle::info_t::config_t::probe(m_path) && !pal::realpath(&m_path, true))
{
// Not existing is not an error.
return true;
Expand Down

0 comments on commit 866808d

Please sign in to comment.