Skip to content

Commit 2ebebaf

Browse files
Copilotpetesramek
andauthored
fix: add GetValues buffer-length validation and bounds documentation
Agent-Logs-Url: https://github.com/petesramek/polyline-algorithm-csharp/sessions/16db7628-2cc2-4c51-982b-0264a04d7157 Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com>
1 parent ee09102 commit 2ebebaf

2 files changed

Lines changed: 44 additions & 1 deletion

File tree

src/PolylineAlgorithm/PolylineFormatter.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,17 @@ internal PolylineFormatter(FormatterRule<T>[] rules) {
6060
/// Output buffer that receives the scaled values.
6161
/// Its length must equal <see cref="Width"/>.
6262
/// </param>
63+
/// <exception cref="ArgumentException">
64+
/// Thrown when <paramref name="values"/>.Length does not equal <see cref="Width"/>.
65+
/// </exception>
6366
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6467
public void GetValues(T item, Span<long> values) {
68+
if (values.Length != Width) {
69+
throw new ArgumentException(
70+
$"Buffer length {values.Length} does not match the formatter width {Width}.",
71+
nameof(values));
72+
}
73+
6574
var rules = _rules; // local copy avoids repeated bounds check on the field
6675
for (var i = 0; i < rules.Length; i++) {
6776
ref var rule = ref rules[i];
@@ -73,7 +82,10 @@ public void GetValues(T item, Span<long> values) {
7382
/// Returns the baseline for the column at <paramref name="index"/>, or <c>0</c> if none is configured.
7483
/// The encoder subtracts this value from the first item's scaled column value during encoding.
7584
/// </summary>
76-
/// <param name="index">The zero-based column index. Must be in the range <c>[0, Width)</c>.</param>
85+
/// <param name="index">
86+
/// The zero-based column index. Must be in the range <c>[0, <see cref="Width"/>)</c>.
87+
/// An <see cref="IndexOutOfRangeException"/> is thrown if the index is out of range.
88+
/// </param>
7789
/// <returns>The baseline value, or <c>0</c> when no baseline has been defined for the column.</returns>
7890
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7991
public long GetBaseline(int index) => _rules[index].Baseline ?? 0L;

tests/PolylineAlgorithm.Tests/PolylineFormatterTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,37 @@ public void GetValues_Scales_Multiple_Columns_Independently() {
353353
Assert.AreEqual(-12025000L, output[1]);
354354
}
355355

356+
[TestMethod]
357+
public void GetValues_With_Wrong_Buffer_Length_Throws_ArgumentException() {
358+
// Arrange — formatter has Width = 2 but buffer has length 1
359+
PolylineFormatter<(double X, double Y)> formatter = FormatterBuilder<(double X, double Y)>.Create()
360+
.AddValue("X", static t => t.X)
361+
.AddValue("Y", static t => t.Y)
362+
.Build();
363+
364+
long[] tooShort = new long[1];
365+
366+
// Act & Assert
367+
ArgumentException ex = Assert.ThrowsExactly<ArgumentException>(
368+
() => formatter.GetValues((1.0, 2.0), tooShort.AsSpan()));
369+
Assert.AreEqual("values", ex.ParamName);
370+
}
371+
372+
[TestMethod]
373+
public void GetValues_With_Oversized_Buffer_Throws_ArgumentException() {
374+
// Arrange — formatter has Width = 1 but buffer has length 3
375+
PolylineFormatter<double> formatter = FormatterBuilder<double>.Create()
376+
.AddValue("Value", static v => v)
377+
.Build();
378+
379+
long[] tooLong = new long[3];
380+
381+
// Act & Assert
382+
ArgumentException ex = Assert.ThrowsExactly<ArgumentException>(
383+
() => formatter.GetValues(1.0, tooLong.AsSpan()));
384+
Assert.AreEqual("values", ex.ParamName);
385+
}
386+
356387
[TestMethod]
357388
public void GetValues_With_Zero_Returns_Zero() {
358389
// Arrange

0 commit comments

Comments
 (0)