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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ ship.

### Changed

- **Local process enumeration.** Ignore nonpositive operating-system process IDs, including the Windows idle
pseudo-process, before filtering and truncation. Unfiltered listings now return attachable process identities
instead of failing when the local catalog contains PID 0.

### Security

### Deployment
Expand Down
7 changes: 7 additions & 0 deletions libs/CheatEngine.Client.Core/Domains/LocalProcessCatalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ internal static bool TryEnumerate(
return Cancel(out result, out failure);
}

// Windows reports the Idle pseudo-process as PID 0. LocalProcessId deliberately models only usable,
// positive process identifiers, so omit system and malformed host rows before they affect the bound.
if (process.Id <= 0)
{
continue;
}

if (Matches(request, process))
{
matches.Add(process);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Diagnostics;

using CheatEngine.Client.Core.Domains;
using CheatEngine.Client.Processes;
using CheatEngine.Client.Results;

namespace CheatEngine.Client.Core.Tests.Domains;

Expand Down Expand Up @@ -41,4 +43,21 @@ public void GetLocalProcessesContainsCopiedMetadataForTheCurrentManagedProcess()

Assert.Equal(current.ProcessName, currentSnapshot.Name);
}

[Fact]
public void LocalCatalogSkipsSystemPseudoProcessesWhileRetainingTheCurrentProcess()
{
using Process current = Process.GetCurrentProcess();
LocalProcessHost host = new();

bool succeeded = LocalProcessCatalog.TryEnumerate(host,
new LocalProcessEnumerationRequest(int.MaxValue), out LocalProcessEnumerationResult result,
out CheatEngineFailure failure, TestContext.Current.CancellationToken);

Assert.True(succeeded);
Assert.Equal(default, failure);
Assert.Contains(result.Processes, process =>
process.Id.Value == current.Id && process.Name == current.ProcessName);
Assert.All(result.Processes, process => Assert.True(process.Id.Value > 0));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,46 @@ public void GetLocalProcessesReturnsBoundedOrderedCopiedLocalMetadata()
Assert.Empty(port.TargetCalls);
}

[Fact]
public void GetLocalProcessesSkipsSystemAndMalformedRowsBeforeApplyingTheBound()
{
(ProcessClient client, FakeLocalProcessHost host, FakeRuntimeObservationPort port) = Create(
[
new LocalProcessInfo(0, "System Idle Process", null),
new LocalProcessInfo(-1, "malformed", null),
new LocalProcessInfo(52, "alpha-worker", "C:\\fixtures\\alpha-worker.exe"),
new LocalProcessInfo(43, "alpha-server", "C:\\fixtures\\alpha-server.exe")
]);

LocalProcessEnumerationResult result = client.GetLocalProcesses(
new LocalProcessEnumerationRequest(1), TestContext.Current.CancellationToken);

Assert.True(result.IsTruncated);
LocalProcessSnapshot snapshot = Assert.Single(result.Processes);
Assert.Equal(new LocalProcessId(43), snapshot.Id);
Assert.Equal("alpha-server", snapshot.Name);
Assert.Equal(1, host.GetLocalProcessesCalls);
Assert.Empty(port.Calls);
Assert.Empty(port.TargetCalls);
}

[Fact]
public void GetLocalProcessesReturnsAnEmptyPageWhenOnlyNonpositiveHostRowsMatch()
{
(ProcessClient client, FakeLocalProcessHost host, _) = Create(
[
new LocalProcessInfo(0, "System Idle Process", null),
new LocalProcessInfo(-4, "malformed", null)
]);

LocalProcessEnumerationResult result = client.GetLocalProcesses(
new LocalProcessEnumerationRequest(1), TestContext.Current.CancellationToken);

Assert.Empty(result.Processes);
Assert.False(result.IsTruncated);
Assert.Equal(1, host.GetLocalProcessesCalls);
}

[Fact]
public void TryGetLocalProcessesReportsACancellationAsNotStartedBeforeReadingTheLocalCatalog()
{
Expand Down
Loading