Assessment reports>Initia>Low findings>Module can be duplicated in module publish requests
Category: Coding Mistakes

Module can be duplicated in module publish requests

Low Severity
Low Impact
Low Likelihood

Description

Initia supports publishing Move modules from Move code. It is implemented as a publish request, which is posted from the Move code, and is executed at the end of the transaction. The newly published module will not be available until the next transaction. There can only be one pending request per transaction, but it is possible to publish an arbitrary number of modules simultaneously at the same owner address.

The following is the signature for the Move function to submit a publication request.

public entry fun publish(
    owner: &signer, 
    module_ids: vector<String>, // 0x1::coin
    code: vector<vector<u8>>,
    upgrade_policy: u8,
) acquires ModuleStore, MetadataStore {

The two arrays, module_ids and code, can both contain duplicates. The same module name may appear multiple times in module_ids, and binary modules with the same name may appear multiple times in code.

The module_ids are immediately deduplicated in the native code.

let mut expected_modules: BTreeSet<String> = BTreeSet::new();
for name in safely_pop_vec_arg!(arguments, Struct) {
    let str_bytes = get_string(name)?;

    context.charge(gas_params.per_byte * NumBytes::new(str_bytes.len() as u64))?;
    expected_modules.insert(String::from_utf8(str_bytes).map_err(|_| {
        SafeNativeError::Abort {
            abort_code: EUNABLE_TO_PARSE_STRING,
        }
    })?);
}

Note the use of BTreeSet, which is a deduplicating container.

The binary modules in code eventually arrive at the following code, which also deduplicates the modules, in a last-overrides-first manner.

let mut map = codes
    .iter()
    .map(|c| {
        let m = CompiledModule::deserialize(c).unwrap();
        (m.self_id(), (c.as_slice(), m))
    })
    .collect::<BTreeMap<_, _>>();

Impact

Fortunately, the impact is limited to unintuitive behavior. Only the final set of deduplicated modules are actually used, with some duplicates silently discarded.

Recommendations

We recommend that duplicate checks be added and an intuitive error be returned.

Remediation

This issue has been acknowledged by Initia Labs, and fixes were implemented in the following commits:

Zellic © 2024Back to top ↑