Skip to content

Commit 95a0d1b

Browse files
committed
Fix errno to use UInt16 per the WASI p1 spec
Per the WebAssembly System Interface (WASI) standard specification, size of `errno` variant is 2 bytes, which is equivalent to `UInt16` in Swift. In WasmKit it's currently specified incorrectly to `UInt32`, which leads to bugs when reading and writing `errno` values in guest memory. Corresponding uses of `WASIAbi.Errno` zero-extend value of 2 bytes to 4 bytes when returning 32-bit integers, since WebAssembly doesn't have a separate 16-bit integer type and zero-extension of narrower integers is the expected behavior. Additionally `ClockId` type specifies a fixed number of cases, disallowing unknown raw values, which could be specified in the future. This edge case is exercised in the WASI specification test suite. The change relaxes this restriction, making the implementation compliant with the test.
1 parent acda030 commit 95a0d1b

File tree

1 file changed

+22
-25
lines changed

1 file changed

+22
-25
lines changed

Sources/WASI/WASI.swift

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ protocol WASI {
220220
}
221221

222222
enum WASIAbi {
223-
enum Errno: UInt32, Error, GuestPointee {
223+
enum Errno: UInt16, Error, GuestPointee {
224224
/// No error occurred. System call completed successfully.
225225
case SUCCESS = 0
226226
/// Argument list too long.
@@ -579,19 +579,20 @@ enum WASIAbi {
579579
}
580580
}
581581

582-
enum ClockId: UInt32, GuestPointee {
582+
struct ClockId: Equatable, RawRepresentable, GuestPointee {
583+
let rawValue: UInt32
583584
/// The clock measuring real time. Time value zero corresponds with
584585
/// 1970-01-01T00:00:00Z.
585-
case REALTIME = 0
586+
static let REALTIME = Self(rawValue: 0)
586587
/// The store-wide monotonic clock, which is defined as a clock measuring
587588
/// real time, whose value cannot be adjusted and which cannot have negative
588589
/// clock jumps. The epoch of this clock is undefined. The absolute time
589590
/// value of this clock therefore has no meaning.
590-
case MONOTONIC = 1
591+
static let MONOTONIC = Self(rawValue: 1)
591592
/// The CPU-time clock associated with the current process.
592-
case PROCESS_CPUTIME_ID = 2
593+
static let PROCESS_CPUTIME_ID = Self(rawValue: 2)
593594
/// The CPU-time clock associated with the current thread.
594-
case THREAD_CPUTIME_ID = 3
595+
static let THREAD_CPUTIME_ID = Self(rawValue: 3)
595596
}
596597

597598
typealias Timestamp = UInt64
@@ -980,7 +981,7 @@ extension WASI {
980981
let (name, type) = entry
981982
functions[name] = WASIHostFunction(type: type) { _, _ in
982983
print("\"\(name)\" not implemented yet")
983-
return [.i32(WASIAbi.Errno.ENOSYS.rawValue)]
984+
return [.i32(.init(WASIAbi.Errno.ENOSYS.rawValue))]
984985
}
985986
}
986987

@@ -1013,7 +1014,7 @@ extension WASI {
10131014
do {
10141015
return try implementation(caller, arguments)
10151016
} catch let errno as WASIAbi.Errno {
1016-
return [.i32(errno.rawValue)]
1017+
return [.i32(.init(errno.rawValue))]
10171018
}
10181019
}
10191020
}
@@ -1026,7 +1027,7 @@ extension WASI {
10261027
argv: .init(memorySpace: buffer, offset: arguments[0].i32),
10271028
argvBuffer: .init(memorySpace: buffer, offset: arguments[1].i32)
10281029
)
1029-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1030+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
10301031
}
10311032
}
10321033

@@ -1039,7 +1040,7 @@ extension WASI {
10391040
argcPointer.pointee = argc
10401041
let bufferSizePointer = UnsafeGuestPointer<WASIAbi.Size>(memorySpace: buffer, offset: arguments[1].i32)
10411042
bufferSizePointer.pointee = bufferSize
1042-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1043+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
10431044
}
10441045
}
10451046

@@ -1051,7 +1052,7 @@ extension WASI {
10511052
environ: .init(memorySpace: buffer, offset: arguments[0].i32),
10521053
environBuffer: .init(memorySpace: buffer, offset: arguments[1].i32)
10531054
)
1054-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1055+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
10551056
}
10561057
}
10571058

@@ -1064,40 +1065,36 @@ extension WASI {
10641065
environSizePointer.pointee = environSize
10651066
let bufferSizePointer = UnsafeGuestPointer<WASIAbi.Size>(memorySpace: buffer, offset: arguments[1].i32)
10661067
bufferSizePointer.pointee = bufferSize
1067-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1068+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
10681069
}
10691070
}
10701071

10711072
preview1["clock_res_get"] = wasiFunction(
10721073
type: .init(parameters: [.i32, .i32], results: [.i32])
10731074
) { caller, arguments in
1074-
guard let id = WASIAbi.ClockId(rawValue: arguments[0].i32) else {
1075-
throw WASIAbi.Errno.EBADF
1076-
}
1075+
let id = WASIAbi.ClockId(rawValue: arguments[0].i32)
10771076
let res = try self.clock_res_get(id: id)
10781077
try withMemoryBuffer(caller: caller) { buffer in
10791078
let resPointer = UnsafeGuestPointer<WASIAbi.Timestamp>(
10801079
memorySpace: buffer, offset: arguments[1].i32
10811080
)
10821081
resPointer.pointee = res
10831082
}
1084-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1083+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
10851084
}
10861085

10871086
preview1["clock_time_get"] = wasiFunction(
10881087
type: .init(parameters: [.i32, .i64, .i32], results: [.i32])
10891088
) { caller, arguments in
1090-
guard let id = WASIAbi.ClockId(rawValue: arguments[0].i32) else {
1091-
throw WASIAbi.Errno.EBADF
1092-
}
1089+
let id = WASIAbi.ClockId(rawValue: arguments[0].i32)
10931090
let time = try self.clock_time_get(id: id, precision: WASIAbi.Timestamp(arguments[1].i64))
10941091
try withMemoryBuffer(caller: caller) { buffer in
10951092
let resPointer = UnsafeGuestPointer<WASIAbi.Timestamp>(
10961093
memorySpace: buffer, offset: arguments[2].i32
10971094
)
10981095
resPointer.pointee = time
10991096
}
1100-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1097+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
11011098
}
11021099

11031100
preview1["fd_advise"] = wasiFunction(
@@ -1112,7 +1109,7 @@ extension WASI {
11121109
fd: arguments[0].i32, offset: arguments[1].i64,
11131110
length: arguments[2].i64, advice: advice
11141111
)
1115-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1112+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
11161113
}
11171114

11181115
preview1["fd_allocate"] = wasiFunction(
@@ -1121,21 +1118,21 @@ extension WASI {
11211118
try self.fd_allocate(
11221119
fd: arguments[0].i32, offset: arguments[1].i64, length: arguments[2].i64
11231120
)
1124-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1121+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
11251122
}
11261123

11271124
preview1["fd_close"] = wasiFunction(
11281125
type: .init(parameters: [.i32], results: [.i32])
11291126
) { caller, arguments in
11301127
try self.fd_close(fd: arguments[0].i32)
1131-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1128+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
11321129
}
11331130

11341131
preview1["fd_datasync"] = wasiFunction(
11351132
type: .init(parameters: [.i32], results: [.i32])
11361133
) { caller, arguments in
11371134
try self.fd_datasync(fd: arguments[0].i32)
1138-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1135+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
11391136
}
11401137

11411138
preview1["fd_fdstat_get"] = wasiFunction(
@@ -1145,7 +1142,7 @@ extension WASI {
11451142
let stat = try self.fd_fdstat_get(fileDescriptor: arguments[0].i32)
11461143
let statPointer = UnsafeGuestPointer<WASIAbi.FdStat>(memorySpace: buffer, offset: arguments[1].i32)
11471144
statPointer.pointee = stat
1148-
return [.i32(WASIAbi.Errno.SUCCESS.rawValue)]
1145+
return [.i32(.init(WASIAbi.Errno.SUCCESS.rawValue))]
11491146
}
11501147
}
11511148

0 commit comments

Comments
 (0)