Skip to content

Commit 409dd5c

Browse files
fix: prevent parsing CLI errors without metadata
When parsing a CLI error, check if any metadata from grpc is present before trying to parse it. Closes #2516
1 parent 7713668 commit 409dd5c

File tree

1 file changed

+22
-19
lines changed

1 file changed

+22
-19
lines changed

arduino-ide-extension/src/node/service-error.ts

+22-19
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ProgrammerIsRequiredForUploadError } from './cli-protocol/cc/arduino/cl
66
type ProtoError = typeof ProgrammerIsRequiredForUploadError;
77
const protoErrorsMap = new Map<string, ProtoError>([
88
[
9-
'type.googleapis.com/cc.arduino.cli.commands.v1.ProgrammerIsRequiredForUploadError',
9+
'cc.arduino.cli.commands.v1.ProgrammerIsRequiredForUploadError',
1010
ProgrammerIsRequiredForUploadError,
1111
],
1212
// handle other cli defined errors here
@@ -22,30 +22,33 @@ export namespace ServiceError {
2222
return arg instanceof Error && isStatusObject(arg);
2323
}
2424

25-
export function isInstanceOf(arg: unknown, type: unknown): boolean {
25+
export function isInstanceOf<ProtoError>(
26+
arg: unknown,
27+
type: new (...args: unknown[]) => ProtoError
28+
): arg is ProtoError {
2629
if (!isStatusObject(arg)) {
2730
return false;
2831
}
2932

30-
const bin = arg.metadata.get('grpc-status-details-bin')[0];
33+
try {
34+
const bin = arg.metadata.get('grpc-status-details-bin')[0];
35+
const uint8Array =
36+
typeof bin === 'string'
37+
? stringToUint8Array(bin)
38+
: new Uint8Array(bin.buffer, bin.byteOffset, bin.byteLength);
3139

32-
const uint8Array =
33-
typeof bin === 'string'
34-
? stringToUint8Array(bin)
35-
: new Uint8Array(bin.buffer, bin.byteOffset, bin.byteLength);
40+
const errors = Status.deserializeBinary(uint8Array)
41+
.getDetailsList()
42+
.map((details) => {
43+
const typeName = details.getTypeName();
44+
const ErrorType = protoErrorsMap.get(typeName);
45+
return ErrorType?.deserializeBinary(details.getValue_asU8());
46+
});
3647

37-
const errors = Status.deserializeBinary(uint8Array)
38-
.getDetailsList()
39-
.map((details) => {
40-
const typeUrl = details.getTypeUrl();
41-
const ErrorType = protoErrorsMap.get(typeUrl);
42-
return ErrorType?.deserializeBinary(details.getValue_asU8());
43-
});
44-
45-
return !!errors.find((error) => {
46-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
47-
return error && error instanceof <any>type;
48-
});
48+
return !!errors.find((error) => error && error instanceof type);
49+
} catch {
50+
return false;
51+
}
4952
}
5053

5154
function isStatusObject(arg: unknown): arg is StatusObject {

0 commit comments

Comments
 (0)