Skip to content

Commit 44098e7

Browse files
authored
Fix the list view to not leak VT decorations (PowerShell#17262)
1 parent 1884693 commit 44098e7

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/System.Management.Automation/FormatAndOutput/common/ListWriter.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics;
77
using System.Management.Automation;
88
using System.Management.Automation.Internal;
9+
using System.Text;
910

1011
namespace Microsoft.PowerShell.Commands.Internal.Format
1112
{
@@ -30,6 +31,11 @@ internal class ListWriter
3031
/// </summary>
3132
private int _columnWidth = 0;
3233

34+
/// <summary>
35+
/// A cached string builder used within this type to reduce creation of temporary strings.
36+
/// </summary>
37+
private readonly StringBuilder _cachedBuilder = new();
38+
3339
/// <summary>
3440
/// </summary>
3541
/// <param name="propertyNames">Names of the properties to display.</param>
@@ -207,7 +213,9 @@ private void WriteProperty(int k, string propertyValue, LineOutput lo)
207213
private void WriteSingleLineHelper(string prependString, string line, LineOutput lo)
208214
{
209215
if (line == null)
216+
{
210217
line = string.Empty;
218+
}
211219

212220
// compute the width of the field for the value string (in screen cells)
213221
int fieldCellCount = _columnWidth - _propertyLabelsDisplayLength;
@@ -221,14 +229,30 @@ private void WriteSingleLineHelper(string prependString, string line, LineOutput
221229
// display the string collection
222230
for (int k = 0; k < sc.Count; k++)
223231
{
232+
string str = sc[k];
233+
_cachedBuilder.Clear();
234+
224235
if (k == 0)
225236
{
226-
lo.WriteLine(PSStyle.Instance.Formatting.FormatAccent + prependString + PSStyle.Instance.Reset + sc[k]);
237+
_cachedBuilder
238+
.Append(PSStyle.Instance.Formatting.FormatAccent)
239+
.Append(prependString)
240+
.Append(PSStyle.Instance.Reset)
241+
.Append(str);
227242
}
228243
else
229244
{
230-
lo.WriteLine(padding + PSStyle.Instance.Formatting.FormatAccent + PSStyle.Instance.Reset + sc[k]);
245+
_cachedBuilder
246+
.Append(padding)
247+
.Append(str);
231248
}
249+
250+
if (str.Contains(ValueStringDecorated.ESC) && !str.EndsWith(PSStyle.Instance.Reset))
251+
{
252+
_cachedBuilder.Append(PSStyle.Instance.Reset);
253+
}
254+
255+
lo.WriteLine(_cachedBuilder.ToString());
232256
}
233257
}
234258

test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,4 +229,17 @@ Describe 'Format-List color tests' {
229229
$out[0] | Should -BeExactly "$($PSStyle.Formatting.FormatAccent)Short : $($PSStyle.Reset)1" -Because ($out[0] | Format-Hex)
230230
$out[1] | Should -BeExactly "$($PSStyle.Formatting.FormatAccent)LongLabelN : $($PSStyle.Reset)2"
231231
}
232+
233+
It 'VT decorations in a property value should not be leaked in list view' {
234+
$expected = @"
235+
`e[32;1ma : `e[0mHello
236+
`e[32;1mb : `e[0m`e[36mworld`e[0m
237+
"@
238+
## Format-List should append the 'reset' escape sequence to the value of 'b' property.
239+
$obj = [pscustomobject]@{ a = "Hello"; b = $PSStyle.Foreground.Cyan + "world"; }
240+
$obj | Format-List | Out-File "$TestDrive/outfile.txt"
241+
242+
$output = Get-Content "$TestDrive/outfile.txt" -Raw
243+
$output.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
244+
}
232245
}

0 commit comments

Comments
 (0)