Merge pull request #5848 from hvitved/csharp/trap-key-escape

C#: Escape IDs in TRAP label definitions
This commit is contained in:
Tom Hvitved
2021-05-10 16:13:13 +02:00
committed by GitHub
72 changed files with 485 additions and 168 deletions

View File

@@ -36,7 +36,7 @@ namespace Semmle.Extraction.CIL
c.Extract(this);
});
#if DEBUG_LABELS
using var writer = new StringWriter();
using var writer = new EscapingTextWriter();
e.WriteId(writer);
var id = writer.ToString();

View File

@@ -29,7 +29,7 @@ namespace Semmle.Extraction.CIL.Entities
public override int GetHashCode() => HashCode.Combine(elementType, rank);
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
elementType.WriteId(trapFile, inContext);
trapFile.Write('[');

View File

@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CIL.Entities
file = new File(cx, cx.AssemblyPath);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(FullName);
trapFile.Write("#file:///");

View File

@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CIL
public override string ToString()
{
using var writer = new StringWriter();
using var writer = new EscapingTextWriter();
WriteQuotedId(writer);
return writer.ToString();
}

View File

@@ -33,7 +33,7 @@ namespace Semmle.Extraction.CIL.Entities
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
ElementType.WriteId(trapFile, inContext);
trapFile.Write('&');

View File

@@ -100,7 +100,7 @@ namespace Semmle.Extraction.CIL.Entities
throw new NotImplementedException();
}
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}

View File

@@ -10,7 +10,7 @@ namespace Semmle.Extraction.CIL.Entities
{
}
public override void WriteId(TextWriter trapFile, bool inContext) => trapFile.Write("<ErrorType>");
public override void WriteId(EscapingTextWriter trapFile, bool inContext) => trapFile.Write("<ErrorType>");
public override CilTypeKind Kind => CilTypeKind.ValueOrRefType;

View File

@@ -20,7 +20,7 @@ namespace Semmle.Extraction.CIL.Entities
ed = cx.MdReader.GetEventDefinition(handle);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
parent.WriteId(trapFile);
trapFile.Write('.');

View File

@@ -14,7 +14,7 @@ namespace Semmle.Extraction.CIL.Entities
{
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(DeclaringType);
trapFile.Write('.');

View File

@@ -14,7 +14,7 @@ namespace Semmle.Extraction.CIL.Entities
TransformedPath = Context.Extractor.PathTransformer.Transform(OriginalPath);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(TransformedPath.DatabaseId);
trapFile.Write(";sourcefile");

View File

@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CIL.Entities
this.transformedPath = path;
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(transformedPath.DatabaseId);
trapFile.Write(";folder");

View File

@@ -42,7 +42,7 @@ namespace Semmle.Extraction.CIL.Entities
public override void WriteAssemblyPrefix(TextWriter trapFile) { }
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
WriteName(
trapFile.Write,

View File

@@ -4,6 +4,6 @@ namespace Semmle.Extraction.CIL.Entities
{
internal interface ITypeSignature
{
void WriteId(TextWriter trapFile, IGenericContext gc);
void WriteId(EscapingTextWriter trapFile, IGenericContext gc);
}
}

View File

@@ -16,7 +16,7 @@ namespace Semmle.Extraction.CIL.Entities
type = t;
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(method);
trapFile.Write('_');

View File

@@ -37,17 +37,15 @@ namespace Semmle.Extraction.CIL.Entities
public virtual IList<LocalVariable>? LocalVariables => throw new NotImplementedException();
public IList<Parameter>? Parameters { get; protected set; }
public override void WriteId(TextWriter trapFile) => WriteMethodId(trapFile, DeclaringType, NameLabel);
public abstract string NameLabel { get; }
protected internal void WriteMethodId(TextWriter trapFile, Type parent, string methodName)
public override void WriteId(EscapingTextWriter trapFile)
{
signature.ReturnType.WriteId(trapFile, this);
trapFile.Write(' ');
parent.WriteId(trapFile);
DeclaringType.WriteId(trapFile);
trapFile.Write('.');
trapFile.Write(methodName);
trapFile.Write(NameLabel);
if (signature.GenericParameterCount > 0)
{
@@ -61,11 +59,9 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.WriteSeparator(",", ref index);
param.WriteId(trapFile, this);
}
trapFile.Write(')');
trapFile.Write(");cil-method");
}
public override string IdSuffix => ";cil-method";
protected IEnumerable<IExtractionProduct> PopulateFlags
{
get

View File

@@ -26,7 +26,7 @@ namespace Semmle.Extraction.CIL.Entities
unboundMethod = (Method)Context.CreateGeneric(gc, ms.Method);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
unboundMethod.WriteId(trapFile);
trapFile.Write('<');

View File

@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CIL.Entities
private readonly Method method;
private readonly int index;
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
if (!(inContext && method == gc))
{

View File

@@ -37,7 +37,7 @@ namespace Semmle.Extraction.CIL.Entities
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
Unmodified.WriteId(trapFile, inContext);
trapFile.Write(IsRequired ? " modreq" : " modopt");

View File

@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CIL.Entities
this.type = type;
}
public void WriteId(TextWriter trapFile, bool inContext)
public void WriteId(EscapingTextWriter trapFile, bool inContext)
{
if (type.IsPrimitiveType)
{

View File

@@ -14,7 +14,7 @@ namespace Semmle.Extraction.CIL.Entities
public bool IsGlobalNamespace => ParentNamespace is null;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
if (ParentNamespace is not null && !ParentNamespace.IsGlobalNamespace)
{
@@ -22,10 +22,9 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write('.');
}
trapFile.Write(Name);
trapFile.Write(";namespace");
}
public override string IdSuffix => ";namespacee";
public override bool Equals(object? obj)
{
if (obj is Namespace ns && Name == ns.Name)

View File

@@ -137,7 +137,7 @@ namespace Semmle.Extraction.CIL.Entities
}
}
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}

View File

@@ -19,7 +19,7 @@ namespace Semmle.Extraction.CIL.Entities
type = t;
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(parameterizable);
trapFile.Write('_');

View File

@@ -20,7 +20,7 @@ namespace Semmle.Extraction.CIL.Entities
public override int GetHashCode() => HashCode.Combine(pointee, nameof(PointerType));
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
pointee.WriteId(trapFile, inContext);
trapFile.Write('*');

View File

@@ -20,7 +20,7 @@ namespace Semmle.Extraction.CIL.Entities
public override int GetHashCode() => typeCode.GetHashCode();
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
Type.WritePrimitiveTypeId(trapFile, Name);
}

View File

@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CIL.Entities
this.type = type;
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(type);
trapFile.Write('.');

View File

@@ -17,7 +17,7 @@ namespace Semmle.Extraction.CIL.Entities
this.shape = shape;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
elementType.WriteId(trapFile, gc);
trapFile.Write('[');
@@ -38,7 +38,7 @@ namespace Semmle.Extraction.CIL.Entities
this.elementType = elementType;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
elementType.WriteId(trapFile, gc);
trapFile.Write('&');
@@ -54,7 +54,7 @@ namespace Semmle.Extraction.CIL.Entities
this.signature = signature;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
FunctionPointerType.WriteName(
trapFile.Write,
@@ -84,7 +84,7 @@ namespace Semmle.Extraction.CIL.Entities
this.typeArguments = typeArguments;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
genericType.WriteId(trapFile, gc);
trapFile.Write('<');
@@ -112,7 +112,7 @@ namespace Semmle.Extraction.CIL.Entities
this.index = index;
}
public void WriteId(TextWriter trapFile, IGenericContext outerGc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext outerGc)
{
if (!ReferenceEquals(innerGc, outerGc) && innerGc is Method method)
{
@@ -132,7 +132,7 @@ namespace Semmle.Extraction.CIL.Entities
this.index = index;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
trapFile.Write("T!");
trapFile.Write(index);
@@ -158,7 +158,7 @@ namespace Semmle.Extraction.CIL.Entities
this.isRequired = isRequired;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
unmodifiedType.WriteId(trapFile, gc);
trapFile.Write(isRequired ? " modreq(" : " modopt(");
@@ -186,7 +186,7 @@ namespace Semmle.Extraction.CIL.Entities
this.elementType = elementType;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
elementType.WriteId(trapFile, gc);
trapFile.Write('*');
@@ -207,7 +207,7 @@ namespace Semmle.Extraction.CIL.Entities
this.typeCode = typeCode;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
trapFile.Write(typeCode.Id());
}
@@ -227,7 +227,7 @@ namespace Semmle.Extraction.CIL.Entities
this.elementType = elementType;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
elementType.WriteId(trapFile, gc);
trapFile.Write("[]");
@@ -248,7 +248,7 @@ namespace Semmle.Extraction.CIL.Entities
this.handle = handle;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
var type = (Type)gc.Context.Create(handle);
type.WriteId(trapFile);
@@ -269,7 +269,7 @@ namespace Semmle.Extraction.CIL.Entities
this.handle = handle;
}
public void WriteId(TextWriter trapFile, IGenericContext gc)
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
var type = (Type)gc.Context.Create(handle);
type.WriteId(trapFile);

View File

@@ -15,7 +15,7 @@ namespace Semmle.Extraction.CIL.Entities
file = cx.CreateSourceFile(location.File);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
file.WriteId(trapFile);
trapFile.Write(',');

View File

@@ -43,11 +43,13 @@ namespace Semmle.Extraction.CIL.Entities
/// (This is to avoid infinite recursion generating a method ID that returns a
/// type parameter.)
/// </param>
public abstract void WriteId(TextWriter trapFile, bool inContext);
public abstract void WriteId(EscapingTextWriter trapFile, bool inContext);
public sealed override void WriteId(TextWriter trapFile) => WriteId(trapFile, false);
public override string IdSuffix => ";cil-type";
public sealed override void WriteId(EscapingTextWriter trapFile)
{
WriteId(trapFile, false);
trapFile.Write(";cil-type");
}
/// <summary>
/// Returns the friendly qualified name of types, such as
@@ -58,10 +60,12 @@ namespace Semmle.Extraction.CIL.Entities
/// </summary>
public string GetQualifiedName()
{
using var writer = new StringWriter();
using var writer = new EscapingTextWriter();
WriteId(writer, false);
var name = writer.ToString();
return name.Substring(name.IndexOf(AssemblyTypeNameSeparator) + 2);
return name.Substring(name.IndexOf(AssemblyTypeNameSeparator) + 2).
Replace(";namespace", "").
Replace(";cil-type", "");
}
public abstract CilTypeKind Kind { get; }

View File

@@ -12,16 +12,6 @@ namespace Semmle.Extraction.CIL.Entities
{
}
public abstract string IdSuffix { get; }
public override void WriteQuotedId(TextWriter trapFile)
{
trapFile.Write("@\"");
WriteId(trapFile);
trapFile.Write(IdSuffix);
trapFile.Write('\"');
}
public abstract IEnumerable<Type> MethodParameters { get; }
public abstract IEnumerable<Type> TypeParameters { get; }
}

View File

@@ -40,7 +40,7 @@ namespace Semmle.Extraction.CIL.Entities
public override int GetHashCode() => handle.GetHashCode();
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}

View File

@@ -88,7 +88,7 @@ namespace Semmle.Extraction.CIL.Entities
public override IEnumerable<Type> ThisGenericArguments => typeParams.Value;
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}

View File

@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CIL.Entities
return type.GetHashCode() * 13 + index;
}
public override void WriteId(TextWriter trapFile, bool inContext)
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
type.WriteId(trapFile, inContext);
trapFile.Write('!');

View File

@@ -69,7 +69,7 @@ namespace Semmle.Extraction.CSharp.Entities
return AssemblyConstructorFactory.Instance.CreateEntity(cx, outputAssemblyCacheKey, null);
}
public override void WriteId(System.IO.TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(assembly.ToString());
if (!(assemblyPath is null))

View File

@@ -20,7 +20,7 @@ namespace Semmle.Extraction.CSharp.Entities
this.entity = entity;
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
if (ReportingLocation?.IsInSource == true)
{
@@ -33,7 +33,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public override void WriteQuotedId(TextWriter trapFile)
public sealed override void WriteQuotedId(EscapingTextWriter trapFile)
{
if (ReportingLocation?.IsInSource == true)
{

View File

@@ -21,7 +21,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation => true;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(Context.CreateLocation(Symbol.Location));
trapFile.Write(";commentblock");

View File

@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation => true;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(Context.CreateLocation(Location));
trapFile.Write(";commentline");

View File

@@ -81,7 +81,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.compilation_finished(this, (float)p.Total.Cpu.TotalSeconds, (float)p.Total.Elapsed.TotalSeconds);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(hashCode);
trapFile.Write(";compilation");

View File

@@ -144,7 +144,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
if (Symbol.IsStatic)
trapFile.Write("static");

View File

@@ -10,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities
private Event(Context cx, IEventSymbol init)
: base(cx, init) { }
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(ContainingType!);
trapFile.Write('.');

View File

@@ -118,7 +118,7 @@ namespace Semmle.Extraction.CSharp.Entities
private readonly Lazy<Type> type;
public Type Type => type.Value;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(Type);
trapFile.Write(" ");

View File

@@ -73,13 +73,13 @@ namespace Semmle.Extraction.CSharp.Entities
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop);
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(ContainingType!);
trapFile.Write('.');
trapFile.Write(Symbol.MetadataName);
trapFile.Write('(');
trapFile.BuildList(",", Symbol.Parameters, (p, tb0) => tb0.WriteSubId(Type.Create(Context, p.Type)));
trapFile.BuildList(",", Symbol.Parameters, p => trapFile.WriteSubId(Type.Create(Context, p.Type)));
trapFile.Write(");indexer");
}

View File

@@ -10,12 +10,12 @@ namespace Semmle.Extraction.CSharp.Entities
{
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
throw new InvalidOperationException();
}
public override void WriteQuotedId(TextWriter trapFile)
public sealed override void WriteQuotedId(EscapingTextWriter trapFile)
{
trapFile.Write('*');
}

View File

@@ -8,12 +8,12 @@ namespace Semmle.Extraction.CSharp.Entities
{
private LocalVariable(Context cx, ISymbol init) : base(cx, init) { }
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
throw new InvalidOperationException();
}
public override void WriteQuotedId(TextWriter trapFile)
public sealed override void WriteQuotedId(EscapingTextWriter trapFile)
{
trapFile.Write('*');
}

View File

@@ -127,7 +127,7 @@ namespace Semmle.Extraction.CSharp.Entities
/// <summary>
/// Factored out to share logic between `Method` and `UserOperator`.
/// </summary>
private static void BuildMethodId(Method m, TextWriter trapFile)
private static void BuildMethodId(Method m, EscapingTextWriter trapFile)
{
m.Symbol.ReturnType.BuildOrWriteId(m.Context, trapFile, m.Symbol);
trapFile.Write(" ");
@@ -153,7 +153,7 @@ namespace Semmle.Extraction.CSharp.Entities
// Type arguments with different nullability can result in
// a constructed method with different nullability of its parameters and return type,
// so we need to create a distinct database entity for it.
trapFile.BuildList(",", m.Symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { ta.Symbol.BuildOrWriteId(m.Context, tb0, m.Symbol); trapFile.Write((int)ta.Nullability); });
trapFile.BuildList(",", m.Symbol.GetAnnotatedTypeArguments(), ta => { ta.Symbol.BuildOrWriteId(m.Context, trapFile, m.Symbol); trapFile.Write((int)ta.Nullability); });
trapFile.Write('>');
}
}
@@ -182,12 +182,12 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
BuildMethodId(this, trapFile);
}
protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method)
protected static void AddParametersToId(Context cx, EscapingTextWriter trapFile, IMethodSymbol method)
{
trapFile.Write('(');
var index = 0;
@@ -222,7 +222,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.Write(')');
}
public static void AddExplicitInterfaceQualifierToId(Context cx, System.IO.TextWriter trapFile, IEnumerable<ISymbol> explicitInterfaceImplementations)
public static void AddExplicitInterfaceQualifierToId(Context cx, EscapingTextWriter trapFile, IEnumerable<ISymbol> explicitInterfaceImplementations)
{
if (explicitInterfaceImplementations.Any())
trapFile.AppendList(",", explicitInterfaceImplementations.Select(impl => cx.CreateEntity(impl.ContainingType)));

View File

@@ -10,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override Location? ReportingLocation => null;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(Symbol);
trapFile.Write(";modifier");

View File

@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation => true;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
if (!Symbol.IsGlobalNamespace)
{

View File

@@ -20,7 +20,7 @@ namespace Semmle.Extraction.CSharp.Entities
this.parent = parent;
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(Context.CreateLocation(ReportingLocation));
trapFile.Write(";namespacedeclaration");

View File

@@ -41,7 +41,7 @@ namespace Semmle.Extraction.CSharp.Entities
get;
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write("loc,");
trapFile.WriteSubId(FileEntity);

View File

@@ -74,7 +74,7 @@ namespace Semmle.Extraction.CSharp.Entities
public static Parameter Create(Context cx, IParameterSymbol param) =>
ParameterFactory.Instance.CreateEntity(cx, param, (param, null, null));
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
if (Parent is null)
Parent = Method.Create(Context, Symbol.ContainingSymbol as IMethodSymbol);
@@ -209,7 +209,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation => true;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write("__arglist;type");
}

View File

@@ -21,7 +21,7 @@ namespace Semmle.Extraction.CSharp.Entities
private Type Type => type.Value;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(Type);
trapFile.Write(" ");

View File

@@ -30,7 +30,7 @@ namespace Semmle.Extraction.CSharp.Entities
PopulateType(trapFile);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(ElementType);
Symbol.BuildArraySuffix(trapFile);

View File

@@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.parent_namespace(this, Namespace.Create(Context, Context.Compilation.GlobalNamespace));
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write("dynamic;type");
}

View File

@@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
Symbol.BuildTypeId(Context, trapFile, Symbol);
trapFile.Write(";functionpointertype");

View File

@@ -128,7 +128,7 @@ namespace Semmle.Extraction.CSharp.Entities
private bool IsAnonymousType() => Symbol.IsAnonymousType || Symbol.Name.Contains("__AnonymousType");
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
if (IsAnonymousType())
{
@@ -141,7 +141,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public override void WriteQuotedId(TextWriter trapFile)
public sealed override void WriteQuotedId(EscapingTextWriter trapFile)
{
if (IsAnonymousType())
trapFile.Write('*');
@@ -195,7 +195,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation => true;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(referencedType);
trapFile.Write(";typeRef");

View File

@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.types(this, Kinds.TypeKind.NULL, "null");
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write("<null>;type");
}

View File

@@ -79,7 +79,7 @@ namespace Semmle.Extraction.CSharp.Entities
return h;
}
public void WriteId(TextWriter trapFile)
public void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(Annotation);
trapFile.Write('(');
@@ -90,7 +90,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override string ToString()
{
using var w = new StringWriter();
using var w = new EscapingTextWriter();
WriteId(w);
return w.ToString();
}
@@ -120,7 +120,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
Symbol.WriteId(trapFile);
}

View File

@@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities
PointedAtType = Create(cx, Symbol.PointedAtType);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(PointedAtType);
trapFile.Write("*;type");

View File

@@ -30,7 +30,7 @@ namespace Semmle.Extraction.CSharp.Entities
// All tuple types are "local types"
public override bool NeedsPopulation => true;
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
Symbol.BuildTypeId(Context, trapFile, Symbol);
trapFile.Write(";tuple");

View File

@@ -103,7 +103,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
string kind;
IEntity containingEntity;

View File

@@ -160,10 +160,10 @@ namespace Semmle.Extraction.CSharp
/// <param name="trapFile">The trap builder used to store the result.</param>
/// <param name="symbolBeingDefined">The outer symbol being defined (to avoid recursive ids).</param>
/// <param name="constructUnderlyingTupleType">Whether to build a type ID for the underlying `System.ValueTuple` struct in the case of tuple types.</param>
public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false) =>
public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false) =>
type.BuildTypeId(cx, trapFile, symbolBeingDefined, true, constructUnderlyingTupleType);
private static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
private static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
{
using (cx.StackGuard)
{
@@ -207,7 +207,7 @@ namespace Semmle.Extraction.CSharp
}
}
private static void BuildOrWriteId(this ISymbol? symbol, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType = false)
private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType = false)
{
if (symbol is null)
{
@@ -249,7 +249,7 @@ namespace Semmle.Extraction.CSharp
/// it will generate an appropriate ID that encodes the signature of
/// <paramref name="symbol" />.
/// </summary>
public static void BuildOrWriteId(this ISymbol? symbol, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined) =>
public static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) =>
symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, true);
/// <summary>
@@ -264,7 +264,7 @@ namespace Semmle.Extraction.CSharp
trapFile.Write(']');
}
private static void BuildAssembly(IAssemblySymbol asm, TextWriter trapFile, bool extraPrecise = false)
private static void BuildAssembly(IAssemblySymbol asm, EscapingTextWriter trapFile, bool extraPrecise = false)
{
var assembly = asm.Identity;
trapFile.Write(assembly.Name);
@@ -282,22 +282,22 @@ namespace Semmle.Extraction.CSharp
trapFile.Write("::");
}
private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined)
private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined)
{
BuildFunctionPointerSignature(funptr, trapFile, (s, tw) => s.BuildOrWriteId(cx, tw, symbolBeingDefined));
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined));
}
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
{
if (!constructUnderlyingTupleType && named.IsTupleType)
{
trapFile.Write('(');
trapFile.BuildList(",", named.TupleElements,
(f, tb0) =>
f =>
{
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
trapFile.Write(":");
f.Type.BuildOrWriteId(cx, tb0, symbolBeingDefined, addBaseClass);
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
}
);
trapFile.Write(")");
@@ -340,7 +340,7 @@ namespace Semmle.Extraction.CSharp
// a constructed type with different nullability of its members and methods,
// so we need to create a distinct database entity for it.
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
(ta, tb0) => ta.Symbol.BuildOrWriteId(cx, tb0, symbolBeingDefined, addBaseClass)
ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass)
);
trapFile.Write('>');
}
@@ -364,7 +364,7 @@ namespace Semmle.Extraction.CSharp
}
}
private static void BuildNamespace(this INamespaceSymbol ns, Context cx, TextWriter trapFile)
private static void BuildNamespace(this INamespaceSymbol ns, Context cx, EscapingTextWriter trapFile)
{
trapFile.WriteSubId(Namespace.Create(cx, ns));
trapFile.Write('.');
@@ -377,7 +377,7 @@ namespace Semmle.Extraction.CSharp
trapFile.Write("<>__AnonType");
trapFile.Write(hackTypeNumber);
trapFile.Write('<');
trapFile.BuildList(",", type.GetMembers().OfType<IPropertySymbol>(), (prop, tb0) => BuildDisplayName(prop.Type, cx, tb0));
trapFile.BuildList(",", type.GetMembers().OfType<IPropertySymbol>(), prop => BuildDisplayName(prop.Type, cx, trapFile));
trapFile.Write('>');
}
@@ -433,7 +433,7 @@ namespace Semmle.Extraction.CSharp
}
public static void BuildFunctionPointerSignature(IFunctionPointerTypeSymbol funptr, TextWriter trapFile,
Action<ITypeSymbol, TextWriter> buildNested)
Action<ITypeSymbol> buildNested)
{
trapFile.Write("delegate* ");
trapFile.Write(funptr.Signature.CallingConvention.ToString().ToLowerInvariant());
@@ -447,19 +447,19 @@ namespace Semmle.Extraction.CSharp
trapFile.Write('<');
trapFile.BuildList(",", funptr.Signature.Parameters,
(p, trap) =>
p =>
{
buildNested(p.Type, trap);
buildNested(p.Type);
switch (p.RefKind)
{
case RefKind.Out:
trap.Write(" out");
trapFile.Write(" out");
break;
case RefKind.In:
trap.Write(" in");
trapFile.Write(" in");
break;
case RefKind.Ref:
trap.Write(" ref");
trapFile.Write(" ref");
break;
}
});
@@ -469,7 +469,7 @@ namespace Semmle.Extraction.CSharp
trapFile.Write(",");
}
buildNested(funptr.Signature.ReturnType, trapFile);
buildNested(funptr.Signature.ReturnType);
if (funptr.Signature.ReturnsByRef)
trapFile.Write(" ref");
@@ -481,7 +481,7 @@ namespace Semmle.Extraction.CSharp
private static void BuildFunctionPointerTypeDisplayName(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile)
{
BuildFunctionPointerSignature(funptr, trapFile, (s, tw) => s.BuildDisplayName(cx, tw));
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildDisplayName(cx, trapFile));
}
private static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Context cx, TextWriter trapFile, bool constructUnderlyingTupleType)
@@ -492,7 +492,7 @@ namespace Semmle.Extraction.CSharp
trapFile.BuildList(
",",
namedType.TupleElements.Select(f => f.Type),
(t, tb0) => t.BuildDisplayName(cx, tb0));
t => t.BuildDisplayName(cx, trapFile));
trapFile.Write(")");
return;
}
@@ -512,11 +512,11 @@ namespace Semmle.Extraction.CSharp
trapFile.BuildList(
",",
namedType.TypeArguments,
(p, tb0) =>
p =>
{
if (IsReallyBound(namedType))
{
p.BuildDisplayName(cx, tb0);
p.BuildDisplayName(cx, trapFile);
}
});
trapFile.Write('>');

View File

@@ -108,7 +108,7 @@ namespace Semmle.Extraction
Populate(init as ISymbol, entity);
#if DEBUG_LABELS
using var id = new StringWriter();
using var id = new EscapingTextWriter();
entity.WriteQuotedId(id);
CheckEntityHasUniqueLabel(id.ToString(), entity);
#endif

View File

@@ -15,9 +15,14 @@ namespace Semmle.Extraction
public Label Label { get; set; }
public abstract void WriteId(TextWriter trapFile);
public abstract void WriteId(EscapingTextWriter trapFile);
public abstract void WriteQuotedId(TextWriter trapFile);
public virtual void WriteQuotedId(EscapingTextWriter trapFile)
{
trapFile.WriteUnescaped("@\"");
WriteId(trapFile);
trapFile.WriteUnescaped('\"');
}
public abstract Location? ReportingLocation { get; }
@@ -27,9 +32,10 @@ namespace Semmle.Extraction
{
trapFile.WriteLabel(this);
trapFile.Write("=");
using var escaping = new EscapingTextWriter(trapFile);
try
{
WriteQuotedId(trapFile);
WriteQuotedId(escaping);
}
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{
@@ -51,7 +57,7 @@ namespace Semmle.Extraction
/// </summary>
public string GetDebugLabel()
{
using var writer = new StringWriter();
using var writer = new EscapingTextWriter();
writer.WriteLabel(Label.Value);
writer.Write('=');
WriteQuotedId(writer);

View File

@@ -29,14 +29,14 @@ namespace Semmle.Extraction
/// Writes the unique identifier of this entitiy to a trap file.
/// </summary>
/// <param name="trapFile">The trapfile to write to.</param>
void WriteId(TextWriter trapFile);
void WriteId(EscapingTextWriter trapFile);
/// <summary>
/// Writes the quoted identifier of this entity,
/// which could be @"..." or *
/// </summary>
/// <param name="trapFile">The trapfile to write to.</param>
void WriteQuotedId(TextWriter trapFile);
void WriteQuotedId(EscapingTextWriter trapFile);
/// <summary>
/// The location for reporting purposes.

View File

@@ -7,12 +7,5 @@ namespace Semmle.Extraction
protected LabelledEntity(Context cx) : base(cx)
{
}
public override void WriteQuotedId(TextWriter trapFile)
{
trapFile.Write("@\"");
WriteId(trapFile);
trapFile.Write('\"');
}
}
}

View File

@@ -9,14 +9,14 @@ namespace Semmle.Extraction
cx.AddFreshLabel(this);
}
public sealed override void WriteId(TextWriter writer)
public sealed override void WriteId(EscapingTextWriter writer)
{
writer.Write('*');
}
public sealed override void WriteQuotedId(TextWriter writer)
public sealed override void WriteQuotedId(EscapingTextWriter writer)
{
WriteId(writer);
writer.Write('*');
}
}
}

View File

@@ -17,7 +17,7 @@ namespace Semmle.Extraction.Entities
public override bool NeedsPopulation => true;
public override void WriteId(System.IO.TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(TransformedPath.DatabaseId);
trapFile.Write(";sourcefile");

View File

@@ -15,7 +15,7 @@ namespace Semmle.Extraction.Entities
public override bool NeedsPopulation => true;
public override void WriteId(System.IO.TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(Symbol.DatabaseId);
trapFile.Write(";folder");

View File

@@ -13,7 +13,7 @@ namespace Semmle.Extraction.Entities
trapFile.files(this, "", "", "");
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write("GENERATED;sourcefile");
}

View File

@@ -17,7 +17,7 @@ namespace Semmle.Extraction.Entities
trapFile.locations_default(this, generatedFile, 0, 0, 0, 0);
}
public override void WriteId(TextWriter trapFile)
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write("loc,");
trapFile.WriteSubId(generatedFile);

View File

@@ -0,0 +1,340 @@
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Semmle.Extraction
{
/// <summary>
/// A `TextWriter` object that wraps another `TextWriter` object, and which
/// HTML escapes the characters `&`, `{`, `}`, `"`, `@`, and `#`, before
/// writing to the underlying object.
/// </summary>
public sealed class EscapingTextWriter : TextWriter
{
private readonly TextWriter wrapped;
private readonly bool disposeUnderlying;
public EscapingTextWriter(TextWriter wrapped, bool disposeUnderlying = false)
{
this.wrapped = wrapped;
this.disposeUnderlying = disposeUnderlying;
}
/// <summary>
/// Creates a new instance with a new underlying `StringWriter` object. The
/// underlying object is disposed of when this object is.
/// </summary>
public EscapingTextWriter() : this(new StringWriter(), true) { }
public EscapingTextWriter(IFormatProvider? formatProvider) : base(formatProvider)
=> throw new NotImplementedException();
private void WriteEscaped(char c)
{
switch (c)
{
case '&':
wrapped.Write("&amp;");
break;
case '{':
wrapped.Write("&lbrace;");
break;
case '}':
wrapped.Write("&rbrace;");
break;
case '"':
wrapped.Write("&quot;");
break;
case '@':
wrapped.Write("&commat;");
break;
case '#':
wrapped.Write("&num;");
break;
default:
wrapped.Write(c);
break;
};
}
public void WriteSubId(IEntity entity)
{
if (entity is null)
{
wrapped.Write("<null>");
return;
}
WriteUnescaped('{');
wrapped.WriteLabel(entity);
WriteUnescaped('}');
}
public void WriteUnescaped(char c)
=> wrapped.Write(c);
public void WriteUnescaped(string s)
=> wrapped.Write(s);
#region overrides
public override Encoding Encoding => wrapped.Encoding;
public override IFormatProvider FormatProvider => wrapped.FormatProvider;
public override string NewLine { get => wrapped.NewLine; }
public override void Close()
=> throw new NotImplementedException();
public override ValueTask DisposeAsync()
=> throw new NotImplementedException();
public override bool Equals(object? obj)
=> wrapped.Equals(obj) && obj is EscapingTextWriter other && disposeUnderlying == other.disposeUnderlying;
public override void Flush()
=> wrapped.Flush();
public override Task FlushAsync()
=> wrapped.FlushAsync();
public override int GetHashCode()
=> HashCode.Combine(wrapped, disposeUnderlying);
public override string ToString()
=> wrapped.ToString() ?? "";
public override void Write(bool value)
=> wrapped.Write(value);
public override void Write(char value)
=> WriteEscaped(value);
public override void Write(char[]? buffer)
{
if (buffer is null)
return;
Write(buffer, 0, buffer.Length);
}
public override void Write(char[] buffer, int index, int count)
{
for (var i = index; i < buffer.Length && i < index + count; i++)
{
WriteEscaped(buffer[i]);
}
}
public override void Write(decimal value)
=> wrapped.Write(value);
public override void Write(double value)
=> wrapped.Write(value);
public override void Write(int value)
=> wrapped.Write(value);
public override void Write(long value)
=> wrapped.Write(value);
public override void Write(object? value)
=> Write(value?.ToString());
public override void Write(ReadOnlySpan<char> buffer)
{
foreach (var c in buffer)
{
WriteEscaped(c);
}
}
public override void Write(float value)
=> wrapped.Write(value);
public override void Write(string? value)
{
if (value is null)
{
wrapped.Write(value);
}
else
{
foreach (var c in value)
{
WriteEscaped(c);
}
}
}
public override void Write(string format, object? arg0)
=> Write(string.Format(format, arg0));
public override void Write(string format, object? arg0, object? arg1)
=> Write(string.Format(format, arg0, arg1));
public override void Write(string format, object? arg0, object? arg1, object? arg2)
=> Write(string.Format(format, arg0, arg1, arg2));
public override void Write(string format, params object?[] arg)
=> Write(string.Format(format, arg));
public override void Write(StringBuilder? value)
{
if (value is null)
{
wrapped.Write(value);
}
else
{
for (var i = 0; i < value.Length; i++)
{
WriteEscaped(value[i]);
}
}
}
public override void Write(uint value)
=> wrapped.Write(value);
public override void Write(ulong value)
=> wrapped.Write(value);
public override Task WriteAsync(char value)
=> throw new NotImplementedException();
public override Task WriteAsync(char[] buffer, int index, int count)
=> throw new NotImplementedException();
public override Task WriteAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public override Task WriteAsync(string? value)
=> throw new NotImplementedException();
public override Task WriteAsync(StringBuilder? value, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public override void WriteLine()
=> wrapped.WriteLine();
public override void WriteLine(bool value)
=> wrapped.WriteLine(value);
public override void WriteLine(char value)
{
Write(value);
WriteLine();
}
public override void WriteLine(char[]? buffer)
{
Write(buffer);
WriteLine();
}
public override void WriteLine(char[] buffer, int index, int count)
{
Write(buffer, index, count);
WriteLine();
}
public override void WriteLine(decimal value)
=> wrapped.WriteLine(value);
public override void WriteLine(double value)
=> wrapped.WriteLine(value);
public override void WriteLine(int value)
=> wrapped.WriteLine(value);
public override void WriteLine(long value)
=> wrapped.WriteLine(value);
public override void WriteLine(object? value)
{
Write(value);
WriteLine();
}
public override void WriteLine(ReadOnlySpan<char> buffer)
{
Write(buffer);
WriteLine();
}
public override void WriteLine(float value)
=> wrapped.WriteLine(value);
public override void WriteLine(string? value)
{
Write(value);
WriteLine();
}
public override void WriteLine(string format, object? arg0)
{
Write(format, arg0);
WriteLine();
}
public override void WriteLine(string format, object? arg0, object? arg1)
{
Write(format, arg0, arg1);
WriteLine();
}
public override void WriteLine(string format, object? arg0, object? arg1, object? arg2)
{
Write(format, arg0, arg1, arg2);
WriteLine();
}
public override void WriteLine(string format, params object?[] arg)
{
Write(format, arg);
WriteLine();
}
public override void WriteLine(StringBuilder? value)
{
Write(value);
WriteLine();
}
public override void WriteLine(uint value)
=> wrapped.WriteLine(value);
public override void WriteLine(ulong value)
=> wrapped.WriteLine(value);
public override Task WriteLineAsync()
=> throw new NotImplementedException();
public override Task WriteLineAsync(char value)
=> throw new NotImplementedException();
public override Task WriteLineAsync(char[] buffer, int index, int count)
=> throw new NotImplementedException();
public override Task WriteLineAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public override Task WriteLineAsync(string? value)
=> throw new NotImplementedException();
public override Task WriteLineAsync(StringBuilder? value, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
protected override void Dispose(bool disposing)
{
if (disposing && disposeUnderlying)
wrapped.Dispose();
}
#endregion overrides
}
}

View File

@@ -17,19 +17,6 @@ namespace Semmle.Extraction
trapFile.WriteLabel(entity.Label.Value);
}
public static void WriteSubId(this TextWriter trapFile, IEntity entity)
{
if (entity is null)
{
trapFile.Write("<null>");
return;
}
trapFile.Write('{');
trapFile.WriteLabel(entity);
trapFile.Write('}');
}
public static void WriteSeparator(this TextWriter trapFile, string separator, ref int index)
{
if (index++ > 0)
@@ -231,9 +218,9 @@ namespace Semmle.Extraction
/// <param name="separator">The separator string (e.g. ",")</param>
/// <param name="items">The list of items.</param>
/// <returns>The original trap builder (fluent interface).</returns>
public static TextWriter AppendList<T>(this TextWriter trapFile, string separator, IEnumerable<T> items) where T : IEntity
public static TextWriter AppendList<T>(this EscapingTextWriter trapFile, string separator, IEnumerable<T> items) where T : IEntity
{
return trapFile.BuildList(separator, items, (x, tb0) => { tb0.WriteSubId(x); });
return trapFile.BuildList(separator, items, x => trapFile.WriteSubId(x));
}
/// <summary>
@@ -245,7 +232,8 @@ namespace Semmle.Extraction
/// <param name="items">The list of items.</param>
/// <param name="action">The action on each item.</param>
/// <returns>The original trap builder (fluent interface).</returns>
public static TextWriter BuildList<T>(this TextWriter trapFile, string separator, IEnumerable<T> items, Action<T, TextWriter> action)
public static T1 BuildList<T1, T2>(this T1 trapFile, string separator, IEnumerable<T2> items, Action<T2> action)
where T1 : TextWriter
{
var first = true;
foreach (var item in items)
@@ -254,7 +242,7 @@ namespace Semmle.Extraction
first = false;
else
trapFile.Write(separator);
action(item, trapFile);
action(item);
}
return trapFile;
}

View File

@@ -0,0 +1 @@
class CheckFileNameEscaping { }