From 2f8fb6596c28fec61cb7363cce260fb8d94ce3cf Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Thu, 9 Jul 2026 21:13:33 -0700 Subject: [PATCH] Fix TOCTOU race in LogOptions.CreateLogger (#252) Read LoggerFactory once into a local so a concurrent SetFactory swap cannot split the ReferenceEquals guard and the CreateLogger call across two different factory instances. Also splits the em-dash remark into two ASCII sentences, matching the sibling ptr727.Utilities fix. Co-Authored-By: Claude Opus 4.8 (1M context) --- LanguageTags/LogOptions.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/LanguageTags/LogOptions.cs b/LanguageTags/LogOptions.cs index e87a4d5..ce154dc 100644 --- a/LanguageTags/LogOptions.cs +++ b/LanguageTags/LogOptions.cs @@ -18,7 +18,7 @@ namespace ptr727.LanguageTags; /// /// /// Note that loggers are created and cached at the time of use by each class instance. Changes to -/// after a logger has been created will not affect existing cached loggers—only new logger requests will use the updated configuration. +/// after a logger has been created will not affect existing cached loggers. Only new logger requests will use the updated configuration. /// /// public static class LogOptions @@ -75,9 +75,10 @@ internal static ILogger CreateLogger(string categoryName) { ArgumentException.ThrowIfNullOrWhiteSpace(categoryName); - // LoggerFactory -> NullLogger - return !ReferenceEquals(LoggerFactory, NullLoggerFactory.Instance) - ? LoggerFactory.CreateLogger(categoryName) + // Read once so a concurrent swap cannot split the check and the create across two instances. + ILoggerFactory factory = LoggerFactory; + return !ReferenceEquals(factory, NullLoggerFactory.Instance) + ? factory.CreateLogger(categoryName) : NullLogger.Instance; } }