Skip to content

Commit 2c462c0

Browse files
authored
Implemented Store.SetLimits (#243)
* Implemented `Store.SetLimits` using the new `wasmtime_store_limiter` function. * Fixed filepath case * Added runtime checking of limiter values * Fixed braces
1 parent af0f880 commit 2c462c0

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

src/Store.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,51 @@ public Store(Engine engine, object? data)
158158
handle = new Handle(Native.wasmtime_store_new(engine.NativeHandle, (IntPtr)storeHandle, Finalizer));
159159
}
160160

161+
/// <summary>
162+
/// Limit the resources that this store may consume. Note that the limits are only used to limit the creation/growth of resources in the future,
163+
/// this does not retroactively attempt to apply limits to the store.
164+
/// </summary>
165+
/// <param name="memorySize">the maximum number of bytes a linear memory can grow to. Growing a linear memory beyond this limit will fail.
166+
/// Pass in a null value to use the default value (unlimited)</param>
167+
/// <param name="tableElements">the maximum number of elements in a table. Growing a table beyond this limit will fail.
168+
/// Pass in a null value to use the default value (unlimited)</param>
169+
/// <param name="instances">the maximum number of instances that can be created for a Store. Module instantiation will fail if this limit is exceeded.
170+
/// Pass in a null value to use the default value (10000)</param>
171+
/// <param name="tables">the maximum number of tables that can be created for a Store. Module instantiation will fail if this limit is exceeded.
172+
/// Pass in a null value to use the default value (10000)</param>
173+
/// <param name="memories">the maximum number of linear memories that can be created for a Store. Instantiation will fail with an error if this limit is exceeded.
174+
/// Pass in a null value to use the default value (10000)</param>
175+
public void SetLimits(long? memorySize = null, uint? tableElements = null, long? instances = null, long? tables = null, long? memories = null)
176+
{
177+
if (memorySize.HasValue && memorySize.Value < 0)
178+
{
179+
throw new ArgumentOutOfRangeException(nameof(memorySize));
180+
}
181+
182+
if (instances.HasValue && instances.Value < 0)
183+
{
184+
throw new ArgumentOutOfRangeException(nameof(instances));
185+
}
186+
187+
if (tables.HasValue && tables.Value < 0)
188+
{
189+
throw new ArgumentOutOfRangeException(nameof(tables));
190+
}
191+
192+
if (memories.HasValue && memories.Value < 0)
193+
{
194+
throw new ArgumentOutOfRangeException(nameof(memories));
195+
}
196+
197+
long tableElements64 = -1;
198+
if (tableElements.HasValue)
199+
{
200+
tableElements64 = tableElements.Value;
201+
}
202+
203+
Native.wasmtime_store_limiter(NativeHandle, memorySize ?? -1, tableElements64, instances ?? -1, tables ?? -1, memories ?? -1);
204+
}
205+
161206
/// <summary>
162207
/// Perform garbage collection within the given store.
163208
/// </summary>
@@ -298,6 +343,9 @@ private static class Native
298343

299344
[DllImport(Engine.LibraryName)]
300345
public static extern void wasmtime_store_delete(IntPtr store);
346+
347+
[DllImport(Engine.LibraryName)]
348+
public static extern void wasmtime_store_limiter(Handle store, long memory_size, long table_elements, long instances, long tables, long memories);
301349
}
302350

303351
private readonly Handle handle;

tests/StoreTests.cs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using FluentAssertions;
2+
using System.IO;
3+
using Xunit;
4+
5+
namespace Wasmtime.Tests
6+
{
7+
public class StoreTests
8+
: StoreFixture
9+
{
10+
[Fact]
11+
public void ItSetsLimits()
12+
{
13+
Store.SetLimits(1, 2, 3, 4, 5);
14+
}
15+
16+
[Fact]
17+
public void ItSetsDefaultLimits()
18+
{
19+
Store.SetLimits(null, null, null, null, null);
20+
}
21+
22+
[Fact]
23+
public void ItLimitsMemorySize()
24+
{
25+
Store.SetLimits(memorySize: Memory.PageSize);
26+
27+
var memory = new Memory(Store, 0, 1024);
28+
memory.GetSize().Should().Be(0);
29+
30+
31+
memory.Grow(1).Should().Be(0);
32+
33+
var act = () => { memory.Grow(1); };
34+
act.Should().Throw<WasmtimeException>();
35+
}
36+
37+
[Fact]
38+
public void ItLimitsTableElements()
39+
{
40+
Store.SetLimits(tableElements: 5);
41+
42+
var table = new Table(Store, ValueKind.ExternRef, null, 0);
43+
table.GetSize().Should().Be(0);
44+
45+
table.Grow(5, null);
46+
47+
var act = () => { table.Grow(1, null); };
48+
act.Should().Throw<WasmtimeException>();
49+
}
50+
51+
[Fact]
52+
public void ItLimitsInstances()
53+
{
54+
Store.SetLimits(instances: 3);
55+
56+
using var module = Module.FromTextFile(Engine, Path.Combine("Modules", "Trap.wat"));
57+
58+
var inst1 = new Instance(Store, module);
59+
var inst2 = new Instance(Store, module);
60+
var inst3 = new Instance(Store, module);
61+
62+
var act = () => { new Instance(Store, module); };
63+
act.Should().Throw<WasmtimeException>();
64+
}
65+
66+
[Fact]
67+
public void ItLimitsTables()
68+
{
69+
Store.SetLimits(tables: 3);
70+
71+
// This module exports exactly 3 tables
72+
using var module = Module.FromTextFile(Engine, Path.Combine("Modules", "TableExports.wat"));
73+
74+
var inst1 = new Instance(Store, module);
75+
76+
var act = () => { new Instance(Store, module); };
77+
act.Should().Throw<WasmtimeException>();
78+
}
79+
80+
[Fact]
81+
public void ItLimitsMemories()
82+
{
83+
Store.SetLimits(memories: 2);
84+
85+
// This module exports 1 memory
86+
using var module = Module.FromTextFile(Engine, Path.Combine("Modules", "MemoryExports.wat"));
87+
88+
var inst1 = new Instance(Store, module);
89+
var inst2 = new Instance(Store, module);
90+
91+
var act = () => { new Instance(Store, module); };
92+
act.Should().Throw<WasmtimeException>();
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)