diff --git a/src/Kiota.Builder/Extensions/StringExtensions.cs b/src/Kiota.Builder/Extensions/StringExtensions.cs
index 3f6fc87d05..7b80cf4702 100644
--- a/src/Kiota.Builder/Extensions/StringExtensions.cs
+++ b/src/Kiota.Builder/Extensions/StringExtensions.cs
@@ -364,6 +364,20 @@ private static string NormalizeSymbolsAfterCleanup(string original)
public static string CleanupXMLString(this string? original)
=> SecurityElement.Escape(original) ?? string.Empty;
+ ///
+ /// Neutralizes block comment delimiters (/* and */) in schema-derived text so it
+ /// cannot break out of a generated block/doc comment. The delimiters are replaced (not
+ /// deleted): deleting a two-character sequence lets the surrounding characters join back into a
+ /// new delimiter (e.g. **// collapses to */). Replacing with a spaced variant
+ /// guarantees no residual */ can re-form.
+ ///
+ /// The original string.
+ /// The string with block comment delimiters neutralized.
+ public static string NeutralizeBlockCommentDelimiters(this string? original)
+ => string.IsNullOrEmpty(original) ? string.Empty :
+ original.Replace("/*", "//*", StringComparison.Ordinal)
+ .Replace("*/", "* /", StringComparison.Ordinal);
+
///
/// Checks if 2 strings are equal, case insensitive
///
diff --git a/src/Kiota.Builder/Writers/Java/JavaConventionService.cs b/src/Kiota.Builder/Writers/Java/JavaConventionService.cs
index fd8d814b93..0afbbffc07 100644
--- a/src/Kiota.Builder/Writers/Java/JavaConventionService.cs
+++ b/src/Kiota.Builder/Writers/Java/JavaConventionService.cs
@@ -154,7 +154,7 @@ public void WriteLongDescription(CodeElement element, LanguageWriter writer, IEn
internal static string RemoveInvalidDescriptionCharacters(string originalDescription) =>
string.IsNullOrEmpty(originalDescription) ?
originalDescription :
- nonAsciiReplaceRegex().Replace(originalDescription.Replace("\\", "/", StringComparison.OrdinalIgnoreCase).Replace("*/", string.Empty, StringComparison.OrdinalIgnoreCase), string.Empty).CleanupXMLString();
+ nonAsciiReplaceRegex().Replace(originalDescription.Replace("\\", "/", StringComparison.OrdinalIgnoreCase), string.Empty).NeutralizeBlockCommentDelimiters().CleanupXMLString();
#pragma warning disable CA1822 // Method should be static
internal void AddRequestBuilderBody(CodeClass parentClass, string returnType, LanguageWriter writer, string? urlTemplateVarName = default, IEnumerable? pathParameters = default)
{
diff --git a/src/Kiota.Builder/Writers/Php/PhpConventionService.cs b/src/Kiota.Builder/Writers/Php/PhpConventionService.cs
index b121060dcc..a7c20e7478 100644
--- a/src/Kiota.Builder/Writers/Php/PhpConventionService.cs
+++ b/src/Kiota.Builder/Writers/Php/PhpConventionService.cs
@@ -140,7 +140,7 @@ private string GetCollectionDocString(CodeParameter codeParameter)
return codeParameter.Optional ? $"{doc}|null" : doc;
}
- internal static string RemoveInvalidDescriptionCharacters(string originalDescription) => originalDescription.Replace("\\", "/", StringComparison.OrdinalIgnoreCase).Replace("*/", string.Empty, StringComparison.OrdinalIgnoreCase);
+ internal static string RemoveInvalidDescriptionCharacters(string originalDescription) => originalDescription.Replace("\\", "/", StringComparison.OrdinalIgnoreCase).NeutralizeBlockCommentDelimiters();
public override bool WriteShortDescription(IDocumentedElement element, LanguageWriter writer, string prefix = "", string suffix = "")
{
ArgumentNullException.ThrowIfNull(writer);
diff --git a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
index 7439ef1936..a623e7efba 100644
--- a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
@@ -1658,7 +1658,7 @@ public void SanitizesMethodDescriptionLinkLabel()
writer.Write(method);
var result = tw.ToString();
Assert.DoesNotContain("see */ more", result);
- Assert.Contains("see more", result);
+ Assert.Contains("see * / more", result);
Assert.Contains("@see (() => new JavaWriter("./", null));
}
+ [Theory]
+ [InlineData("**//", "** //")] // deletion would re-form "*/"; replacement must not
+ [InlineData("**\\/", "** //")] // backslash normalization must not re-form "*/"
+ [InlineData("*\u00e9/", "* /")] // non-ASCII strip must run before delimiter neutralization
+ [InlineData("*/", "* /")]
+ [InlineData("/*", "//*")]
+ [InlineData("normal description", "normal description")]
+ [InlineData("", "")]
+ public void RemoveInvalidDescriptionCharactersNeutralizesCommentBreakout(string input, string expected)
+ {
+ var result = JavaConventionService.RemoveInvalidDescriptionCharacters(input);
+ Assert.Equal(expected, result);
+ Assert.DoesNotContain("*/", result, StringComparison.Ordinal);
+ }
}
diff --git a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs
index 2229faa142..02e516720c 100644
--- a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs
@@ -289,7 +289,7 @@ public async Task WriteRequestExecutorAsync()
Assert.Contains("public function post(): Promise", result);
Assert.Contains("$requestInfo = $this->createPostRequestInformation();", result);
Assert.DoesNotContain("@link https://learn.microsoft.com/ Learning */ docs", result);
- Assert.Contains("@link https://learn.microsoft.com/ Learning docs", result);
+ Assert.Contains("@link https://learn.microsoft.com/ Learning * / docs", result);
Assert.Contains("'401' => [Error401::class, 'createFromDiscriminatorValue']", result);
Assert.Contains("$result = $this->requestAdapter->sendPrimitiveAsync($requestInfo, StreamInterface::class, $errorMappings);", result);
Assert.Contains("return $result;", result);
diff --git a/tests/Kiota.Builder.Tests/Writers/Php/PhpWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Php/PhpWriterTests.cs
index fb027c8e77..d17af3ff87 100644
--- a/tests/Kiota.Builder.Tests/Writers/Php/PhpWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Php/PhpWriterTests.cs
@@ -32,6 +32,19 @@ public void WriteSomething()
Assert.Throws(() => new PhpWriter(null, "graph"));
Assert.Throws(() => new PhpWriter("./", null));
}
+ [Theory]
+ [InlineData("**//", "** //")] // deletion would re-form "*/"; replacement must not
+ [InlineData("**\\/", "** //")] // backslash normalization must not re-form "*/"
+ [InlineData("*/", "* /")]
+ [InlineData("/*", "//*")]
+ [InlineData("legit /* nested */ text", "legit //* nested * / text")]
+ [InlineData("normal description", "normal description")]
+ public void RemoveInvalidDescriptionCharactersNeutralizesCommentBreakout(string input, string expected)
+ {
+ var result = PhpConventionService.RemoveInvalidDescriptionCharacters(input);
+ Assert.Equal(expected, result);
+ Assert.DoesNotContain("*/", result, StringComparison.Ordinal);
+ }
public void Dispose()
{
tw?.Dispose();