Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: schema index signature type unsoundness #1007

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions kclvm/runtime/src/_kclvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ kclvm_value_ref_t* kclvm_builtin_oct(kclvm_context_t* ctx, kclvm_value_ref_t* ar

kclvm_value_ref_t* kclvm_builtin_option(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs);

void kclvm_builtin_option_init(kclvm_context_t* ctx, int8_t* key, int8_t* value);
void kclvm_builtin_option_init(kclvm_context_t* ctx, char* key, char* value);

kclvm_value_ref_t* kclvm_builtin_option_reset(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs);

Expand Down Expand Up @@ -224,13 +224,13 @@ void kclvm_context_set_disable_schema_check(kclvm_context_t* p, kclvm_bool_t v);

void kclvm_context_set_import_names(kclvm_context_t* p, kclvm_value_ref_t* import_names);

void kclvm_context_set_kcl_filename(kclvm_context_t* ctx, int8_t* filename);
void kclvm_context_set_kcl_filename(kclvm_context_t* ctx, char* filename);

void kclvm_context_set_kcl_line_col(kclvm_context_t* ctx, int32_t line, int32_t col);

void kclvm_context_set_kcl_location(kclvm_context_t* p, int8_t* filename, int32_t line, int32_t col);
void kclvm_context_set_kcl_location(kclvm_context_t* p, char* filename, int32_t line, int32_t col);

void kclvm_context_set_kcl_pkgpath(kclvm_context_t* p, int8_t* pkgpath);
void kclvm_context_set_kcl_pkgpath(kclvm_context_t* p, char* pkgpath);

void kclvm_context_set_list_option_mode(kclvm_context_t* p, kclvm_bool_t v);

Expand Down Expand Up @@ -422,9 +422,9 @@ kclvm_value_ref_t* kclvm_net_to_IP4(kclvm_context_t* ctx, kclvm_value_ref_t* arg

void kclvm_plugin_init(void* fn_ptr);

kclvm_value_ref_t* kclvm_plugin_invoke(kclvm_context_t* ctx, int8_t* method, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs);
kclvm_value_ref_t* kclvm_plugin_invoke(kclvm_context_t* ctx, char* method, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs);

char* kclvm_plugin_invoke_json(int8_t* method, char* args, char* kwargs);
char* kclvm_plugin_invoke_json(char* method, char* args, char* kwargs);

kclvm_value_ref_t* kclvm_regex_compile(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs);

Expand Down
12 changes: 6 additions & 6 deletions kclvm/runtime/src/_kclvm_api_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@
// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_context_main_end_hook(%kclvm_context_t* %p, %kclvm_value_ref_t* %return_value);

// api-spec: kclvm_context_set_kcl_location
// api-spec(c): void kclvm_context_set_kcl_location(kclvm_context_t* p, int8_t* filename, int32_t line, int32_t col);
// api-spec(c): void kclvm_context_set_kcl_location(kclvm_context_t* p, char* filename, int32_t line, int32_t col);
// api-spec(llvm): declare void @kclvm_context_set_kcl_location(%kclvm_context_t* %p, i8* %filename, i32 %line, i32 %col);

// api-spec: kclvm_context_set_kcl_pkgpath
// api-spec(c): void kclvm_context_set_kcl_pkgpath(kclvm_context_t* p, int8_t* pkgpath);
// api-spec(c): void kclvm_context_set_kcl_pkgpath(kclvm_context_t* p, char* pkgpath);
// api-spec(llvm): declare void @kclvm_context_set_kcl_pkgpath(%kclvm_context_t* %p, i8* %pkgpath);

// api-spec: kclvm_context_set_kcl_filename
// api-spec(c): void kclvm_context_set_kcl_filename(kclvm_context_t* ctx, int8_t* filename);
// api-spec(c): void kclvm_context_set_kcl_filename(kclvm_context_t* ctx, char* filename);
// api-spec(llvm): declare void @kclvm_context_set_kcl_filename(%kclvm_context_t* %ctx, i8* %filename);

// api-spec: kclvm_context_set_kcl_line_col
Expand Down Expand Up @@ -967,7 +967,7 @@
// api-spec(llvm): declare void @kclvm_assert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg);

// api-spec: kclvm_builtin_option_init
// api-spec(c): void kclvm_builtin_option_init(kclvm_context_t* ctx, int8_t* key, int8_t* value);
// api-spec(c): void kclvm_builtin_option_init(kclvm_context_t* ctx, char* key, char* value);
// api-spec(llvm): declare void @kclvm_builtin_option_init(%kclvm_context_t* %ctx, i8* %key, i8* %value);

// api-spec: kclvm_builtin_option_reset
Expand Down Expand Up @@ -1087,11 +1087,11 @@
// api-spec(llvm): declare void @kclvm_plugin_init(i8* %fn_ptr);

// api-spec: kclvm_plugin_invoke
// api-spec(c): kclvm_value_ref_t* kclvm_plugin_invoke(kclvm_context_t* ctx, int8_t* method, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs);
// api-spec(c): kclvm_value_ref_t* kclvm_plugin_invoke(kclvm_context_t* ctx, char* method, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs);
// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_plugin_invoke(%kclvm_context_t* %ctx, i8* %method, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs);

// api-spec: kclvm_plugin_invoke_json
// api-spec(c): char* kclvm_plugin_invoke_json(int8_t* method, char* args, char* kwargs);
// api-spec(c): char* kclvm_plugin_invoke_json(char* method, char* args, char* kwargs);
// api-spec(llvm): declare i8* @kclvm_plugin_invoke_json(i8* %method, i8* %args, i8* %kwargs);

// api-spec: kclvm_units_to_n
Expand Down
25 changes: 15 additions & 10 deletions kclvm/runtime/src/value/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1086,18 +1086,23 @@ pub unsafe extern "C" fn kclvm_dict_set_value(
let val = ptr_as_ref(val);
if p.is_config() {
p.dict_update_key_value(key, val.clone());
}
if p.is_schema() {
let schema: ValueRef;
{
let schema_value = p.as_schema();
let mut config_keys = schema_value.config_keys.clone();
config_keys.push(key.to_string());
schema = resolve_schema(mut_ptr_as_ref(ctx), p, &config_keys);
if p.is_schema() {
let schema: ValueRef;
{
let schema_value = p.as_schema();
let mut config_keys = schema_value.config_keys.clone();
config_keys.push(key.to_string());
schema = resolve_schema(mut_ptr_as_ref(ctx), p, &config_keys);
}
p.schema_update_with_schema(&schema);
}
p.schema_update_with_schema(&schema);
} else {
panic!(
"failed to update the dict. An iterable of key-value pairs was expected, but got {}. Check if the syntax for updating the dictionary with the attribute '{}' is correct",
p.type_str(),
key
);
}
/*panic*/
}

#[no_mangle]
Expand Down
6 changes: 5 additions & 1 deletion kclvm/runtime/src/value/val_dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,11 @@ impl ValueRef {
Value::schema_value(schema) => {
schema.config.values.insert(key.to_string(), val);
}
_ => panic!("invalid dict update value: {}", self.type_str()),
_ => panic!(
"failed to update the dict. An iterable of key-value pairs was expected, but got {}. Check if the syntax for updating the dictionary with the attribute '{}' is correct",
self.type_str(),
key
),
}
}

Expand Down
2 changes: 1 addition & 1 deletion kclvm/runtime/src/value/val_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ impl ValueRef {
let attr_map = match &*binding {
Value::schema_value(schema) => &schema.config.values,
Value::dict_value(schema) => &schema.values,
_ => panic!("Invalid schema/dict value, got {}", self.type_str()),
_ => panic!("invalid schema or dict value, got {}", self.type_str()),
};
let optional_mapping = self.schema_optional_mapping();
let optional_mapping_ref = optional_mapping.rc.borrow();
Expand Down
6 changes: 5 additions & 1 deletion kclvm/runtime/src/value/val_union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,11 @@ impl ValueRef {
}
if union_schema {
let result = self.clone();
let optional_mapping = self.schema_optional_mapping();
let optional_mapping = if self.is_schema() {
self.schema_optional_mapping()
} else {
x.schema_optional_mapping()
};
let schema = result.dict_to_schema(
name.as_str(),
pkgpath.as_str(),
Expand Down
12 changes: 12 additions & 0 deletions kclvm/sema/src/resolver/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl<'ctx> Resolver<'ctx> {
if let (Some(index_signature), Some(index_signature_node)) =
(scope_ty.index_signature, &schema_stmt.index_signature)
{
// Insert the schema index signature key name into the scope.
if let Some(key_name) = index_signature.key_name {
let (start, end) = index_signature_node.get_span_pos();
self.insert_object(
Expand All @@ -88,6 +89,17 @@ impl<'ctx> Resolver<'ctx> {
},
)
}
// Check index signature default value type.
if let Some(value) = &index_signature_node.node.value {
let expected_ty = index_signature.val_ty;
let value_ty = self.expr(value);
self.must_assignable_to(
value_ty,
expected_ty,
index_signature_node.get_span_pos(),
None,
);
}
}
let schema_attr_names = schema_stmt.get_left_identifier_list();
for (line, column, name) in schema_attr_names {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
schema WithComponent:
name: str

schema WithComponents:
[name: str]: WithComponent = 1
1 change: 1 addition & 0 deletions kclvm/sema/src/resolver/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ fn test_resolve_program_fail() {
"mutable_error_1.k",
"unique_key_error_0.k",
"unique_key_error_1.k",
"unmatched_index_sign_default_value.k",
"unmatched_args.k",
];
for case in cases {
Expand Down
6 changes: 3 additions & 3 deletions kclvm/sema/src/resolver/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ impl<'ctx> Resolver<'ctx> {
range: &Range,
) -> bool {
if let Some(index_signature) = &schema_ty.index_signature {
if !assignable_to(val_ty.clone(), index_signature.val_ty.clone()) {
if !self.check_type(val_ty.clone(), index_signature.val_ty.clone(), range) {
self.handler.add_type_error(
&format!(
"expected schema index signature value type {}, got {}",
Expand All @@ -248,8 +248,8 @@ impl<'ctx> Resolver<'ctx> {
);
}
if index_signature.any_other {
return assignable_to(key_ty, index_signature.key_ty.clone())
&& assignable_to(val_ty, index_signature.val_ty.clone());
return self.check_type(key_ty, index_signature.key_ty.clone(), range)
&& self.check_type(val_ty, index_signature.val_ty.clone(), range);
}
true
} else {
Expand Down
4 changes: 4 additions & 0 deletions test/grammar/schema/assign_stmt/fail_0/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
schema Schema:
a.b = 1

s = Schema {}
18 changes: 18 additions & 0 deletions test/grammar/schema/assign_stmt/fail_0/stderr.golden.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sys
import os

import kclvm.kcl.error as kcl_error

cwd = os.path.dirname(os.path.realpath(__file__))

kcl_error.print_kcl_error_message(
kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE,
file_msgs=[
kcl_error.ErrFileMsg(
filename=cwd + "/main.k",
line_no=2,
),
],
arg_msg="failed to update the dict. An iterable of key-value pairs was expected, but got UndefinedType. Check if the syntax for updating the dictionary with the attribute 'b' is correct")
, file=sys.stdout
)
10 changes: 10 additions & 0 deletions test/grammar/schema/index_signature/fail_10/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
schema WithComponent:
name: str
$type: str

schema WithComponents:
[name: str]: WithComponent = WithComponent {name: name}

components: WithComponents {
ws: {}
}
18 changes: 18 additions & 0 deletions test/grammar/schema/index_signature/fail_10/stderr.golden.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sys
import os

import kclvm.kcl.error as kcl_error

cwd = os.path.dirname(os.path.realpath(__file__))

kcl_error.print_kcl_error_message(
kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE,
file_msgs=[
kcl_error.ErrFileMsg(
filename=cwd + "/main.k",
line_no=9,
),
],
arg_msg="attribute 'type' of WithComponent is required and can't be None or Undefined")
, file=sys.stdout
)
10 changes: 10 additions & 0 deletions test/grammar/schema/index_signature/fail_11/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
schema WithComponent:
name: str
$type: str

schema WithComponents:
[name: str]: WithComponent = WithComponent {name: name}

components: WithComponents {
ws = {}
}
18 changes: 18 additions & 0 deletions test/grammar/schema/index_signature/fail_11/stderr.golden.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sys
import os

import kclvm.kcl.error as kcl_error

cwd = os.path.dirname(os.path.realpath(__file__))

kcl_error.print_kcl_error_message(
kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE,
file_msgs=[
kcl_error.ErrFileMsg(
filename=cwd + "/main.k",
line_no=9,
),
],
arg_msg="attribute 'name' of WithComponent is required and can't be None or Undefined")
, file=sys.stdout
)
10 changes: 10 additions & 0 deletions test/grammar/schema/index_signature/fail_7/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
schema WithComponent:
name: str
$type: str

schema WithComponents:
[name: str]: WithComponent = {name: name}

components: WithComponents {
ws: {}
}
18 changes: 18 additions & 0 deletions test/grammar/schema/index_signature/fail_7/stderr.golden.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sys
import os

import kclvm.kcl.error as kcl_error

cwd = os.path.dirname(os.path.realpath(__file__))

kcl_error.print_kcl_error_message(
kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE,
file_msgs=[
kcl_error.ErrFileMsg(
filename=cwd + "/main.k",
line_no=9,
),
],
arg_msg="attribute 'type' of WithComponent is required and can't be None or Undefined")
, file=sys.stdout
)
10 changes: 10 additions & 0 deletions test/grammar/schema/index_signature/fail_8/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
schema WithComponent:
name: str
$type: str

schema WithComponents:
[name: str]: WithComponent = {name: name}

components: WithComponents {
ws: WithComponent {}
}
18 changes: 18 additions & 0 deletions test/grammar/schema/index_signature/fail_8/stderr.golden.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sys
import os

import kclvm.kcl.error as kcl_error

cwd = os.path.dirname(os.path.realpath(__file__))

kcl_error.print_kcl_error_message(
kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE,
file_msgs=[
kcl_error.ErrFileMsg(
filename=cwd + "/main.k",
line_no=9,
),
],
arg_msg="attribute 'type' of WithComponent is required and can't be None or Undefined")
, file=sys.stdout
)
10 changes: 10 additions & 0 deletions test/grammar/schema/index_signature/fail_9/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
schema WithComponent:
name: str
$type: str

schema WithComponents:
[name: str]: WithComponent = WithComponent {name: name}

components: WithComponents {
ws: WithComponent {}
}
18 changes: 18 additions & 0 deletions test/grammar/schema/index_signature/fail_9/stderr.golden.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sys
import os

import kclvm.kcl.error as kcl_error

cwd = os.path.dirname(os.path.realpath(__file__))

kcl_error.print_kcl_error_message(
kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE,
file_msgs=[
kcl_error.ErrFileMsg(
filename=cwd + "/main.k",
line_no=9,
),
],
arg_msg="attribute 'type' of WithComponent is required and can't be None or Undefined")
, file=sys.stdout
)
2 changes: 1 addition & 1 deletion test/grammar/schema/index_signature/key_alias_1/main.k
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
schema TeamSpec:
fullName: str
name = id
name: str = id
shortName: str = name

schema TeamMap:
Expand Down
Loading
Loading