| 254 | } |
| 255 | |
| 256 | void ArgFlow::mergeArray(const ArgFlow &CalleeArgFlowResult, CallBase &C) { |
| 257 | |
| 258 | IsArray |= CalleeArgFlowResult.IsArray; |
| 259 | IsVariableLenArray |= CalleeArgFlowResult.IsVariableLenArray; |
| 260 | IsFilePathString |= CalleeArgFlowResult.IsFilePathString; |
| 261 | |
| 262 | auto CalleeArrIdxes = CalleeArgFlowResult.ArrIndexes; |
| 263 | ArrIndexes.insert(CalleeArrIdxes.begin(), CalleeArrIdxes.end()); |
| 264 | |
| 265 | // If the value is Array and this value is a field in struct, |
| 266 | // merge field info also. |
| 267 | if (CalleeArgFlowResult.FDInfo) { |
| 268 | if (CalleeArgFlowResult.IsArray) |
| 269 | this->FDInfo->SizeFields.insert( |
| 270 | CalleeArgFlowResult.FDInfo->SizeFields.begin(), |
| 271 | CalleeArgFlowResult.FDInfo->SizeFields.end()); |
| 272 | else if (CalleeArgFlowResult.IsArrayLen) |
| 273 | this->FDInfo->ArrayFields.insert( |
| 274 | CalleeArgFlowResult.FDInfo->ArrayFields.begin(), |
| 275 | CalleeArgFlowResult.FDInfo->ArrayFields.end()); |
| 276 | } else if (CalleeArgFlowResult.IsArray) { |
| 277 | // Result is for Argument, need to merge Size/Array Argument Info |
| 278 | // Find arguments of caller function (==current function) that |
| 279 | // a size argument in the callee function depends on. |
| 280 | for (auto *SizeArg : CalleeArgFlowResult.SizeArgs) { |
| 281 | auto *V = C.getArgOperand(SizeArg->getArgNo()); |
| 282 | if (this->FDInfo) { |
| 283 | collectRelatedLengthField(*V); |
| 284 | ArgFlow &ParentResult = this->FDInfo->Parent; |
| 285 | for (unsigned FieldNum : this->FDInfo->SizeFields) { |
| 286 | ArgFlow &LenFieldResult = ParentResult.getOrCreateFieldFlow(FieldNum); |
| 287 | LenFieldResult.setToArrLen(this->FDInfo->FieldNum); |
| 288 | } |
| 289 | } else |
| 290 | collectRelatedLengthArg(*V); |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | // if argument/value is struct, merge each fields result also |
| 295 | if (!CalleeArgFlowResult.STInfo) |
| 296 | return; |
| 297 | |
| 298 | if (!this->isStruct()) |
| 299 | this->setStruct(CalleeArgFlowResult.STInfo->StructType); |
| 300 | |
| 301 | for (auto Result : CalleeArgFlowResult.STInfo->FieldResults) { |
| 302 | if (!Result.second) |
| 303 | continue; |
| 304 | unsigned FieldNum = Result.first; |
| 305 | ArgFlow &FieldResult = this->getOrCreateFieldFlow(FieldNum); |
| 306 | ArgFlow &CalleeResult = *Result.second; |
| 307 | FieldResult.mergeArray(CalleeResult, C); |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | // Used for analyze ArrayLen |
| 312 | // First tracking the value used as array index (findRelatedField) then |
no test coverage detected