mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:40:11 +01:00
Deduction can do conversion, and conversion can import impls from the Core package. If you have the right number of impls in your ImplStore at that moment, it will reallocate and any pointer into context.impls() will be invalidated. In particular, in impl lookup, we currentl loop over context.impls() and do deduction on each impl. So this can break the for loop. Additionally, we pass around a reference to the currently-being-looked-at Impl, which becomes invalidated. This is very challenging to test in any reliable way as you need a specific number of impls in your ImplStore. I hit it when making changes to a test in the middle of a bunch of file splits. Putting the same test in its own file did not trigger the issue. It was caught by ASAN, which showed: - The memory was allocated by SmallVector in handle_impl when making the Impl. - The memory was freed by SmallVector reallocating in import_ref.cpp - The memory was accessed when reading through the `impl` reference in FindWitnessInImpls(). I was able to reproduce by printing the `impl.interface.interface_id` after the call to GetWitnessIdForImpl() which does the deduction. I didn't save the ASAN stack and now I can't find the exact permutation of the test file that caused it to occur in order to reproduce. :( To avoid the UAF we stop passing around the Impl reference, and pass around either the ImplId, or values from the Impl. To avoid copying the entirety of the impl ids in context.impls() into a separate container in order to iterate safely, we move the early outs from GetWitnessIdForImpl() up to the caller where it can use them to reduce the number impl ids that we iterate over. Type structures will be able to further reduce the size of this set.
42 lines
1.5 KiB
C++
42 lines
1.5 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_CHECK_DEDUCE_H_
|
|
#define CARBON_TOOLCHAIN_CHECK_DEDUCE_H_
|
|
|
|
#include "toolchain/check/context.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
// Deduces the generic arguments to use in a call to a generic.
|
|
auto DeduceGenericCallArguments(
|
|
Context& context, SemIR::LocId loc_id, SemIR::GenericId generic_id,
|
|
SemIR::SpecificId enclosing_specific_id, SemIR::InstId self_type_id,
|
|
SemIR::InstBlockId implicit_params_id, SemIR::InstBlockId params_id,
|
|
SemIR::InstId self_id, llvm::ArrayRef<SemIR::InstId> arg_ids)
|
|
-> SemIR::SpecificId;
|
|
|
|
// Data from the `Impl` that is used by deduce.
|
|
//
|
|
// We don't use a reference to an `Impl` as deduction can invalidate the
|
|
// reference by causing impl declarations to be imported from `Core` during
|
|
// conversion.
|
|
struct DeduceImpl {
|
|
SemIR::InstId self_id;
|
|
SemIR::GenericId generic_id;
|
|
SemIR::SpecificId specific_id;
|
|
};
|
|
|
|
// Deduces the impl arguments to use in a use of a parameterized impl. Returns
|
|
// `None` if deduction fails.
|
|
auto DeduceImplArguments(Context& context, SemIR::LocId loc_id, DeduceImpl impl,
|
|
SemIR::ConstantId self_id,
|
|
SemIR::SpecificId constraint_specific_id)
|
|
-> SemIR::SpecificId;
|
|
|
|
} // namespace Carbon::Check
|
|
|
|
#endif // CARBON_TOOLCHAIN_CHECK_DEDUCE_H_
|