{"record":{"id":"d18f0c91dc78edc7","repo":"dotnet/wpf","slug":"cannot-set-seek-pointer-to-a-negative-position-d18f0c","errorCode":null,"errorMessage":"Cannot set seek pointer to a negative position.","messagePattern":"Cannot set seek pointer to a negative position\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/RightsManagementEncryptedStream.cs","lineNumber":149,"sourceCode":"                        {\n                            temp = _streamPosition + offset;\n                            break;\n                        }\n                    case SeekOrigin.End:\n                        {\n                            temp = Length + offset;\n                            break;\n                        }\n                    default:\n                        {\n                            throw new ArgumentOutOfRangeException(nameof(origin), SR.SeekOriginInvalid);\n                        }\n                }\n            }\n            \n            if (temp < 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(offset), SR.SeekNegative);\n            }\n\n            _streamPosition = temp;\n            return _streamPosition;\n        }        \n\n        /// <summary>\n        /// See .NET Framework SDK under System.IO.Stream\n        /// </summary>\n        public override void SetLength(long newLength)\n        {\n            CheckDisposed(); \n            \n            if (newLength < 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(newLength), SR.CannotMakeStreamLengthNegative);\n            }\n","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/RightsManagementEncryptedStream.cs#L131-L167","documentation":"RightsManagementEncryptedStream.Seek validates the computed position before applying it. When the seek origin (Begin/Current/End) combined with the offset yields a negative position, the stream throws ArgumentOutOfRangeException rather than allowing an invalid stream cursor. This mirrors the contract of System.IO.Stream.Seek, where positions must be >= 0.","triggerScenarios":"Calling Seek(offset, SeekOrigin.Begin) with a negative offset; Seek(offset, SeekOrigin.Current) when the current _streamPosition plus offset is negative; Seek(offset, SeekOrigin.End) with an offset whose absolute value exceeds the cached stream length.","commonSituations":"Computing a seek offset from parsed lengths or user data without clamping; seeking backwards past the start while reading an encrypted rights-managed package; a corrupted length header causing End-relative math to go negative.","solutions":["Check that offset + current position (for SeekOrigin.Current) or offset alone (for SeekOrigin.Begin) is >= 0 before calling Seek.","For SeekOrigin.End, clamp the offset so |offset| <= stream length: long safeOffset = Math.Max(offset, -stream.Length);","Compute the absolute target position with Math.Max(0, target) when negative positions are semantically meaningless for your reader.","If the negative value comes from parsed package metadata, re-verify/correct the data source; the stream itself is healthy.","Wrap Seek in try-catch (ArgumentOutOfRangeException) if inputs are untrusted, and recover by seeking to 0."],"exampleFix":"// before\nencryptedStream.Seek(-100, SeekOrigin.Begin);\n// after\nlong target = Math.Max(0, -100);\nencryptedStream.Seek(target, SeekOrigin.Begin);","handlingStrategy":"validation","validationCode":"long target = origin switch\n{\n    SeekOrigin.Begin => offset,\n    SeekOrigin.Current => stream.Position + offset,\n    SeekOrigin.End => stream.Length + offset,\n    _ => throw new ArgumentOutOfRangeException(nameof(origin))\n};\nif (target < 0) target = 0; // or reject","typeGuard":"bool IsValidSeek(long length, long offset, SeekOrigin origin)\n{\n    long target = origin switch\n    {\n        SeekOrigin.Begin => offset,\n        SeekOrigin.Current => stream.Position + offset,\n        SeekOrigin.End => length + offset,\n        _ => long.MinValue\n    };\n    return target >= 0;\n}","tryCatchPattern":"try { stream.Seek(offset, origin); }\ncatch (ArgumentOutOfRangeException ex) { /* clamp or report: ex.ParamName == \"offset\" */ stream.Seek(0, SeekOrigin.Begin); }","preventionTips":["Compute absolute target positions before seeking and clamp to [0, Length].","Never feed untrusted parsed lengths directly into Seek offsets.","Prefer SeekOrigin.Begin with a validated absolute position over relative arithmetic.","Unit-test edge offsets (Length, -Length, 0) for stream readers."],"tags":["argumentoutofrange","stream","seek","rights-management"],"backgroundTag":"argument-out-of-range","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}