Permissions, RateControl and Auditing

This commit is contained in:
2026-07-16 14:01:08 +03:00
parent 3a1b95dbc5
commit ba64a0c95a
62 changed files with 6095 additions and 2366 deletions
+12
View File
@@ -56,6 +56,18 @@ internal static class ParserGuard
"collection");
}
internal static void EnsureTypeMetadataDepth(Warehouse? warehouse, int depth)
{
// Some compatibility entry points accept a null Warehouse. Keep those safe by
// applying the built-in default rather than silently disabling this stack guard.
var limit = warehouse?.Configuration.Parser.MaximumTypeMetadataDepth
?? ParserConfiguration.DefaultMaximumTypeMetadataDepth;
if (limit > 0 && depth > limit)
throw new ParserLimitException(
$"TRU type metadata depth of {depth} exceeds the configured limit of {limit}.");
}
internal static ulong MultiplySaturated(ulong value, ulong multiplier)
=> value > ulong.MaxValue / multiplier ? ulong.MaxValue : value * multiplier;
}
+29 -41
View File
@@ -37,7 +37,7 @@ namespace Esiur.Data;
public class StringKeyList : IEnumerable<KeyValuePair<string, string>>
{
private List<KeyValuePair<string, string>> m_Variables = new List<KeyValuePair<string, string>>();
private readonly List<KeyValuePair<string, string>> m_Variables = new List<KeyValuePair<string, string>>();
private bool allowMultiple;
@@ -54,44 +54,32 @@ public class StringKeyList : IEnumerable<KeyValuePair<string, string>>
if (OnModified != null)
OnModified(key, value);
key = key.ToLower();
if (!allowMultiple)
{
foreach (var kv in m_Variables)
{
if (kv.Key.ToLower() == key)
{
m_Variables.Remove(kv);
break;
}
}
var index = m_Variables.FindIndex(
item => string.Equals(item.Key, key, StringComparison.OrdinalIgnoreCase));
if (index >= 0)
m_Variables.RemoveAt(index);
}
m_Variables.Add(new KeyValuePair<string, string>(key, value));
m_Variables.Add(new KeyValuePair<string, string>(key.ToLowerInvariant(), value));
}
public string this[string key]
{
get
{
key = key.ToLower();
foreach (var kv in m_Variables)
if (kv.Key.ToLower() == key)
if (string.Equals(kv.Key, key, StringComparison.OrdinalIgnoreCase))
return kv.Value;
return null;
}
set
{
key = key.ToLower();
var toRemove = m_Variables.Where(x => x.Key.ToLower() == key).ToArray();
foreach (var item in toRemove)
m_Variables.Remove(item);
key = key.ToLowerInvariant();
m_Variables.RemoveAll(
item => string.Equals(item.Key, key, StringComparison.OrdinalIgnoreCase));
m_Variables.Add(new KeyValuePair<string, string>(key, value));
OnModified?.Invoke(key, value);
@@ -121,12 +109,10 @@ public class StringKeyList : IEnumerable<KeyValuePair<string, string>>
public List<string> GetValues(string Key)
{
var key = Key.ToLower();
List<string> values = new List<string>();
foreach (var kv in m_Variables)
if (kv.Key.ToLower() == key)
if (string.Equals(kv.Key, Key, StringComparison.OrdinalIgnoreCase))
values.Add(kv.Value);
return values;
@@ -134,22 +120,26 @@ public class StringKeyList : IEnumerable<KeyValuePair<string, string>>
public void RemoveAll(string key)
{
while (Remove(key)) { }
for (var i = m_Variables.Count - 1; i >= 0; i--)
{
if (!string.Equals(m_Variables[i].Key, key, StringComparison.OrdinalIgnoreCase))
continue;
m_Variables.RemoveAt(i);
OnModified?.Invoke(key, null);
}
}
public bool Remove(string key)
{
key = key.ToLower();
foreach (var kv in m_Variables)
for (var i = 0; i < m_Variables.Count; i++)
{
if (kv.Key.ToLower() == key)
{
if (OnModified != null)
OnModified(key, null);
m_Variables.Remove(kv);
return true;
}
if (!string.Equals(m_Variables[i].Key, key, StringComparison.OrdinalIgnoreCase))
continue;
m_Variables.RemoveAt(i);
OnModified?.Invoke(key, null);
return true;
}
return false;
@@ -162,9 +152,8 @@ public class StringKeyList : IEnumerable<KeyValuePair<string, string>>
public bool ContainsKey(string key)
{
key = key.ToLower();
foreach (var kv in m_Variables)
if (kv.Key.ToLower() == key)
if (string.Equals(kv.Key, key, StringComparison.OrdinalIgnoreCase))
return true;
return false;
}
@@ -172,12 +161,11 @@ public class StringKeyList : IEnumerable<KeyValuePair<string, string>>
public bool ContainsValue(string value)
{
value = value.ToLower();
foreach (var kv in m_Variables)
if (kv.Value.ToLower() == value)
if (string.Equals(kv.Value, value, StringComparison.OrdinalIgnoreCase))
return true;
return false;
}
}
}
+23 -4
View File
@@ -666,7 +666,16 @@ namespace Esiur.Data
//}
public static IParseResult<Tru> Parse(byte[] data, uint offset, Warehouse warehouse)
=> Parse(data, offset, warehouse, 1);
private static IParseResult<Tru> Parse(
byte[] data,
uint offset,
Warehouse warehouse,
int depth)
{
ParserGuard.EnsureTypeMetadataDepth(warehouse, depth);
var oOffset = offset;
var header = data[offset++];
@@ -753,7 +762,7 @@ namespace Esiur.Data
var subTypes = new Tru[subsCount];
for (var i = 0; i < subsCount; i++)
{
var pr = Tru.Parse(data, offset, warehouse);
var pr = Parse(data, offset, warehouse, depth + 1);
subTypes[i] = pr.Value;
offset += pr.Size;
}
@@ -793,8 +802,18 @@ namespace Esiur.Data
public static async AsyncReply<IParseResult<Tru>> ParseAsync(byte[] data, uint offset, EpConnection connection, ulong[] requestSequence)
public static AsyncReply<IParseResult<Tru>> ParseAsync(byte[] data, uint offset, EpConnection connection, ulong[] requestSequence)
=> ParseAsync(data, offset, connection, requestSequence, 1);
private static async AsyncReply<IParseResult<Tru>> ParseAsync(
byte[] data,
uint offset,
EpConnection connection,
ulong[] requestSequence,
int depth)
{
ParserGuard.EnsureTypeMetadataDepth(ParserGuard.GetWarehouse(connection), depth);
var oOffset = offset;
var header = data[offset++];
@@ -891,7 +910,7 @@ namespace Esiur.Data
var subTypes = new Tru[subsCount];
for (var i = 0; i < subsCount; i++)
{
var pr = await Tru.ParseAsync(data, offset, connection, requestSequence);
var pr = await ParseAsync(data, offset, connection, requestSequence, depth + 1);
subTypes[i] = pr.Value;
offset += pr.Size;
}
@@ -930,4 +949,4 @@ namespace Esiur.Data
}
}
}
}
}