Skip to content

Commit 30dfb9b

Browse files
wangzhaodeQxinyu
authored andcommitted
[CPU:Bugfix] Fix ConvInt8 SIGSEGV when Conv lacks quantized weight
在 `CPUConvolution.cpp` 和 `CPUBackend.cpp` 中添加了检查,确保在执行 `ConvInt8` 操作时具有量化权重数据,以防止因缺少量化权重而导致的空指针解引用崩溃。 Link: https://code.alibaba-inc.com/AliNN/AliNNPrivate/codereview/28339484 * [CPU:Bugfix] Fix ConvInt8 SIGSEGV when Conv lacks quantized weight GitOrigin-RevId: 3ab854da7248261bcf77ff0d89fa9589df23cb0b
1 parent 4419e33 commit 30dfb9b

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

source/backend/cpu/CPUBackend.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,31 @@ static OpType _getRealOpType(OpType opType) {
654654
return opType;
655655
}
656656
}
657+
658+
// A Conv / DepthwiseConv may be promoted to Int8 execution purely based on the
659+
// int8 quantAttr of its input/output tensors. Guard against promoting an op that
660+
// carries no quantized weight data (e.g. a Conv listed in skip_quant_op_names but
661+
// still surrounded by int8 tensors): the ConvInt8 executor would later dereference
662+
// a missing quan weight (null symmetricQuan) and crash. Non-conv ops are unaffected.
663+
static bool _convHasQuantWeight(const MNN::Op* op) {
664+
auto opType = op->type();
665+
if (opType != OpType_Convolution && opType != OpType_ConvolutionDepthwise) {
666+
return true;
667+
}
668+
auto conv2d = op->main_as_Convolution2D();
669+
if (nullptr == conv2d) {
670+
return false;
671+
}
672+
auto quan = conv2d->quanParameter();
673+
if (nullptr != quan && (nullptr != quan->buffer() || nullptr != conv2d->external())) {
674+
return true;
675+
}
676+
auto symmetric = conv2d->symmetricQuan();
677+
if (nullptr != symmetric && nullptr != symmetric->weight()) {
678+
return true;
679+
}
680+
return false;
681+
}
657682
void* CPUBackend::onMapTensor(Tensor::MapType mtype, Tensor::DimensionType dtype, const Tensor* srcTensor) {
658683
if (static_cast<int>(getBytes(this, srcTensor)) != srcTensor->getType().bytes()) {
659684
return nullptr;
@@ -732,7 +757,7 @@ Execution* CPUBackend::onCreate(const std::vector<Tensor*>& inputs, const std::v
732757
if (outputs.size() > 0 && inputs.size() > 0) {
733758
bool outputQuant = TensorUtils::getDescribe(outputs[0])->quantAttr != nullptr && TensorUtils::getDescribe(outputs[0])->quantAttr->type == DataType_DT_INT8;
734759
bool inputQuant = TensorUtils::getDescribe(inputs[0])->quantAttr != nullptr && TensorUtils::getDescribe(inputs[0])->quantAttr->type == DataType_DT_INT8;
735-
if (inputQuant && outputQuant) {
760+
if (inputQuant && outputQuant && _convHasQuantWeight(op)) {
736761
opType = _getRealOpType(opType);
737762
}
738763
}

source/backend/cpu/CPUConvolution.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,16 @@ class CPUConvInt8Creator : public CPUBackend::Creator {
342342
quanCommon = ConvolutionCommon::load(op, backend, false, true);
343343

344344
}
345+
// A ConvInt8 op must carry quantized weight data, either as quanCommon
346+
// (from quanParameter / external) or as an inline symmetricQuan weight.
347+
// Without either, DenseConvInt8TiledExecutor would dereference a null
348+
// weight pointer and crash. Reject explicitly instead.
349+
if (nullptr == quanCommon &&
350+
(nullptr == convOp->symmetricQuan() || nullptr == convOp->symmetricQuan()->weight())) {
351+
MNN_ERROR("CPUConvInt8Creator: op '%s' has no quantized weight data for ConvInt8 execution\n",
352+
op->name() ? op->name()->c_str() : "unknown");
353+
return nullptr;
354+
}
345355
// auto res = CPUConvolution::makeResourceInt8(backend, op, core->pack);
346356
// return new DenseConvInt8TiledExecutor(backend, op, res);
347357

0 commit comments

Comments
 (0)