Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit edc7dcd

Browse files
committed
Issue fixed: dangling pointer that 'UnsafeMutablePointer()' casused made invalid model outputs
Issue fixed: dangling pointer that 'UnsafeMutablePointer()' casused made invalid model outputs
1 parent 0678fd7 commit edc7dcd

File tree

9 files changed

+111
-58
lines changed

9 files changed

+111
-58
lines changed

D2Go/D2Go/Live/LiveObjectDetectionViewController.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,43 +17,51 @@ class LiveObjectDetectionViewController: ViewController {
1717
private var cameraController = CameraController()
1818
private var imageViewLive = UIImageView()
1919
private var inferencer = ObjectDetector()
20-
20+
2121
override func viewDidLoad() {
2222
super.viewDidLoad()
2323
cameraController.configPreviewLayer(cameraView)
2424
imageViewLive.frame = CGRect(x: 0, y: 0, width: cameraView.frame.size.width, height: cameraView.frame.size.height)
2525
cameraView.addSubview(imageViewLive)
26-
26+
2727
cameraController.videoCaptureCompletionBlock = { [weak self] buffer, error in
2828
guard let strongSelf = self else { return }
2929
if error != nil {
3030
return
3131
}
32-
guard var pixelBuffer = buffer else { return }
33-
32+
guard let pixelBuffer = buffer else { return }
33+
3434
let currentTimestamp = CACurrentMediaTime()
3535
if (currentTimestamp - strongSelf.prevTimestampMs) * 1000 <= strongSelf.delayMs { return }
3636
strongSelf.prevTimestampMs = currentTimestamp
37+
38+
// UnsafeMutablePointer() doesn't guarantee that the converted pointer points to the memory that is still being allocated
39+
// So we create a new pointer and copy the &pixelBuffer's memory to where it points to
40+
let copiedBufferPtr = UnsafeMutablePointer<Float>.allocate(capacity: pixelBuffer.count)
41+
copiedBufferPtr.initialize(from: pixelBuffer, count: pixelBuffer.count)
42+
3743
let startTime = CACurrentMediaTime()
38-
guard let outputs = self?.inferencer.module.detect(image: &pixelBuffer) else {
44+
guard let outputs = self?.inferencer.module.detect(image: copiedBufferPtr) else {
45+
copiedBufferPtr.deallocate()
3946
return
4047
}
48+
copiedBufferPtr.deallocate()
4149
let inferenceTime = CACurrentMediaTime() - startTime
42-
50+
4351
DispatchQueue.main.async {
4452
let ivScaleX : Double = Double(strongSelf.imageViewLive.frame.size.width / CGFloat(PrePostProcessor.inputWidth))
4553
let ivScaleY : Double = Double(strongSelf.imageViewLive.frame.size.height / CGFloat(PrePostProcessor.inputHeight))
4654

4755
let startX = Double((strongSelf.imageViewLive.frame.size.width - CGFloat(ivScaleX) * CGFloat(PrePostProcessor.inputWidth))/2)
4856
let startY = Double((strongSelf.imageViewLive.frame.size.height - CGFloat(ivScaleY) * CGFloat(PrePostProcessor.inputHeight))/2)
49-
57+
5058
let predictions = PrePostProcessor.outputsToPredictions(outputs: outputs, imgScaleX: 1.0, imgScaleY: 1.0, ivScaleX: ivScaleX, ivScaleY: ivScaleY, startX: startX, startY: startY)
5159

5260
PrePostProcessor.cleanDetection(imageView: strongSelf.imageViewLive)
5361
strongSelf.indicator.isHidden = true
5462
strongSelf.benchmarkLabel.isHidden = false
5563
strongSelf.benchmarkLabel.text = String(format: "%.2fms", 1000*inferenceTime)
56-
64+
5765
PrePostProcessor.showDetection(imageView: strongSelf.imageViewLive, nmsPredictions: predictions, classes: strongSelf.inferencer.classes)
5866
}
5967
}

D2Go/D2Go/ViewController.swift

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavig
1010
@IBOutlet weak var imageView: UIImageView!
1111
@IBOutlet weak var btnRun: UIButton!
1212
@IBOutlet weak var btnNext: UIButton!
13-
13+
1414
private let testImages = ["test1.png", "test2.jpg", "test3.png"]
1515
private var imgIndex = 0
1616

1717
private var image : UIImage?
1818
private var inferencer = ObjectDetector()
19-
19+
2020
override func viewDidLoad() {
2121
super.viewDidLoad()
2222
image = UIImage(named: testImages[imgIndex])!
@@ -31,27 +31,33 @@ class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavig
3131
btnRun.setTitle("Running the model...", for: .normal)
3232

3333
let resizedImage = image!.resized(to: CGSize(width: CGFloat(PrePostProcessor.inputWidth), height: CGFloat(PrePostProcessor.inputHeight)))
34-
34+
3535
let imgScaleX = Double(image!.size.width / CGFloat(PrePostProcessor.inputWidth));
3636
let imgScaleY = Double(image!.size.height / CGFloat(PrePostProcessor.inputHeight));
37-
37+
3838
let ivScaleX : Double = (image!.size.width > image!.size.height ? Double(imageView.frame.size.width / imageView.image!.size.width) : Double(imageView.image!.size.width / imageView.image!.size.height))
3939
let ivScaleY : Double = (image!.size.height > image!.size.width ? Double(imageView.frame.size.height / imageView.image!.size.height) : Double(imageView.image!.size.height / imageView.image!.size.width))
4040

4141
let startX = Double((imageView.frame.size.width - CGFloat(ivScaleX) * imageView.image!.size.width)/2)
4242
let startY = Double((imageView.frame.size.height - CGFloat(ivScaleY) * imageView.image!.size.height)/2)
4343

44-
guard var pixelBuffer = resizedImage.normalized() else {
44+
guard let pixelBuffer = resizedImage.normalized() else {
4545
return
4646
}
47-
47+
4848
DispatchQueue.global().async {
49-
guard let outputs = self.inferencer.module.detect(image: &pixelBuffer) else {
49+
// UnsafeMutablePointer() doesn't guarantee that the converted pointer points to the memory that is still being allocated
50+
// So we create a new pointer and copy the &pixelBuffer's memory to where it points to
51+
let copiedBufferPtr = UnsafeMutablePointer<Float>.allocate(capacity: pixelBuffer.count)
52+
copiedBufferPtr.initialize(from: pixelBuffer, count: pixelBuffer.count)
53+
guard let outputs = self.inferencer.module.detect(image: copiedBufferPtr) else {
54+
copiedBufferPtr.deallocate()
5055
return
5156
}
52-
57+
copiedBufferPtr.deallocate()
58+
5359
let predictions = PrePostProcessor.outputsToPredictions(outputs: outputs, imgScaleX: imgScaleX, imgScaleY: imgScaleY, ivScaleX: ivScaleX, ivScaleY: ivScaleY, startX: startX, startY: startY)
54-
60+
5561
DispatchQueue.main.async {
5662
PrePostProcessor.showDetection(imageView: self.imageView, nmsPredictions: predictions, classes: self.inferencer.classes)
5763
self.btnRun.isEnabled = true
@@ -75,7 +81,7 @@ class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavig
7581
imagePickerController.sourceType = .photoLibrary
7682
self.present(imagePickerController, animated: true, completion: nil)
7783
}
78-
84+
7985
@IBAction func cameraTapped(_ sender: Any) {
8086
PrePostProcessor.cleanDetection(imageView: imageView)
8187
if UIImagePickerController.isSourceTypeAvailable(.camera) {
@@ -85,13 +91,11 @@ class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavig
8591
self.present(imagePickerController, animated: true, completion: nil)
8692
}
8793
}
88-
94+
8995
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
9096
image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
9197
image = image!.resized(to: CGSize(width: CGFloat(PrePostProcessor.inputWidth), height: CGFloat(PrePostProcessor.inputHeight)*image!.size.height/image!.size.width))
9298
imageView.image = image
9399
self.dismiss(animated: true, completion: nil)
94100
}
95101
}
96-
97-

HelloWorld-CoreML/HelloWorld/HelloWorld/ViewController.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ class ViewController: UIViewController {
2626
let image = UIImage(named: "image.png")!
2727
imageView.image = image
2828
let resizedImage = image.resized(to: CGSize(width: 224, height: 224))
29-
guard var pixelBuffer = resizedImage.normalized() else {
29+
guard let pixelBuffer = resizedImage.normalized() else {
3030
return
3131
}
32-
guard let outputs = module.predict(image: UnsafeMutableRawPointer(&pixelBuffer)) else {
32+
// UnsafeMutablePointer() doesn't guarantee that the converted pointer points to the memory that is still being allocated
33+
// So we create a new pointer and copy the &pixelBuffer's memory to where it points to
34+
let copiedBufferPtr = UnsafeMutablePointer<Float>.allocate(capacity: pixelBuffer.count)
35+
copiedBufferPtr.initialize(from: pixelBuffer, count: pixelBuffer.count)
36+
guard let outputs = module.predict(image: copiedBufferPtr) else {
37+
copiedBufferPtr.deallocate()
3338
return
3439
}
40+
copiedBufferPtr.deallocate()
3541
let zippedResults = zip(labels.indices, outputs)
3642
let sortedResults = zippedResults.sorted { $0.1.floatValue > $1.1.floatValue }.prefix(3)
3743
var text = ""

HelloWorld-Metal/HelloWorld-Metal/HelloWorld-Metal/ViewController.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ class ViewController: UIViewController {
2626
let image = UIImage(named: "image.png")!
2727
imageView.image = image
2828
let resizedImage = image.resized(to: CGSize(width: 224, height: 224))
29-
guard var pixelBuffer = resizedImage.normalized() else {
29+
guard let pixelBuffer = resizedImage.normalized() else {
3030
return
3131
}
32-
guard let outputs = module.predict(image: UnsafeMutableRawPointer(&pixelBuffer)) else {
32+
// UnsafeMutablePointer() doesn't guarantee that the converted pointer points to the memory that is still being allocated
33+
// So we create a new pointer and copy the &pixelBuffer's memory to where it points to
34+
let copiedBufferPtr = UnsafeMutablePointer<Float>.allocate(capacity: pixelBuffer.count)
35+
copiedBufferPtr.initialize(from: pixelBuffer, count: pixelBuffer.count)
36+
guard let outputs = module.predict(image: copiedBufferPtr) else {
37+
copiedBufferPtr.deallocate()
3338
return
3439
}
40+
copiedBufferPtr.deallocate()
3541
let zippedResults = zip(labels.indices, outputs)
3642
let sortedResults = zippedResults.sorted { $0.1.floatValue > $1.1.floatValue }.prefix(3)
3743
var text = ""

HelloWorld/HelloWorld/HelloWorld/ViewController.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ class ViewController: UIViewController {
2626
let image = UIImage(named: "image.png")!
2727
imageView.image = image
2828
let resizedImage = image.resized(to: CGSize(width: 224, height: 224))
29-
guard var pixelBuffer = resizedImage.normalized() else {
29+
guard let pixelBuffer = resizedImage.normalized() else {
3030
return
3131
}
32-
guard let outputs = module.predict(image: UnsafeMutableRawPointer(&pixelBuffer)) else {
32+
// UnsafeMutablePointer() doesn't guarantee that the converted pointer points to the memory that is still being allocated
33+
// So we create a new pointer and copy the &pixelBuffer's memory to where it points to
34+
let copiedBufferPtr = UnsafeMutablePointer<Float>.allocate(capacity: pixelBuffer.count)
35+
copiedBufferPtr.initialize(from: pixelBuffer, count: pixelBuffer.count)
36+
guard let outputs = module.predict(image: copiedBufferPtr) else {
37+
copiedBufferPtr.deallocate()
3338
return
3439
}
40+
copiedBufferPtr.deallocate()
3541
let zippedResults = zip(labels.indices, outputs)
3642
let sortedResults = zippedResults.sorted { $0.1.floatValue > $1.1.floatValue }.prefix(3)
3743
var text = ""

ImageSegmentation/ImageSegmentation/ViewController.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import UIKit
33
class ViewController: UIViewController {
44
@IBOutlet weak var imageView: UIImageView!
55
@IBOutlet weak var btnSegment: UIButton!
6-
6+
77
private var imageName = "deeplab.jpg"
88
private var image : UIImage?
99
private let imageHelper = UIImageHelper()
@@ -17,7 +17,7 @@ class ViewController: UIViewController {
1717
fatalError("Can't find the model file!")
1818
}
1919
}()
20-
20+
2121
override func viewDidLoad() {
2222
super.viewDidLoad()
2323

@@ -30,22 +30,27 @@ class ViewController: UIViewController {
3030
btnSegment.isEnabled = false
3131
btnSegment.setTitle("Running the model...", for: .normal)
3232
let resizedImage = image!.resized(to: CGSize(width: 250, height: 250))
33-
guard var pixelBuffer = resizedImage.normalized() else {
33+
guard let pixelBuffer = resizedImage.normalized() else {
3434
return
3535
}
36-
36+
3737
let w = Int32(resizedImage.size.width)
3838
let h = Int32(resizedImage.size.height)
3939
DispatchQueue.global().async {
40-
let buffer = self.module.segment(image: UnsafeMutableRawPointer(&pixelBuffer), withWidth:w, withHeight: h)
40+
// UnsafeMutablePointer() doesn't guarantee that the converted pointer points to the memory that is still being allocated
41+
// So we create a new pointer and copy the &pixelBuffer's memory to where it points to
42+
let copiedBufferPtr = UnsafeMutablePointer<Float>.allocate(capacity: pixelBuffer.count)
43+
copiedBufferPtr.initialize(from: pixelBuffer, count: pixelBuffer.count)
44+
let buffer = self.module.segment(image: copiedBufferPtr, withWidth:w, withHeight: h)
45+
copiedBufferPtr.deallocate()
4146
DispatchQueue.main.async {
4247
self.imageView.image = self.imageHelper.convertRGBBuffer(toUIImage: buffer , withWidth: w, withHeight: h)
4348
self.btnSegment.isEnabled = true
4449
self.btnSegment.setTitle("Segment", for: .normal)
4550
}
4651
}
4752
}
48-
53+
4954
@IBAction func doRestart(_ sender: Any) {
5055
if imageName == "deeplab.jpg" {
5156
imageName = "dog.jpg"
@@ -55,6 +60,5 @@ class ViewController: UIViewController {
5560
}
5661
image = UIImage(named: imageName)!
5762
imageView.image = image
58-
}
63+
}
5964
}
60-

ObjectDetection/ObjectDetection/Live/LiveObjectDetectionViewController.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,43 +17,51 @@ class LiveObjectDetectionViewController: ViewController {
1717
private var cameraController = CameraController()
1818
private var imageViewLive = UIImageView()
1919
private var inferencer = ObjectDetector()
20-
20+
2121
override func viewDidLoad() {
2222
super.viewDidLoad()
2323
cameraController.configPreviewLayer(cameraView)
2424
imageViewLive.frame = CGRect(x: 0, y: 0, width: cameraView.frame.size.width, height: cameraView.frame.size.height)
2525
cameraView.addSubview(imageViewLive)
26-
26+
2727
cameraController.videoCaptureCompletionBlock = { [weak self] buffer, error in
2828
guard let strongSelf = self else { return }
2929
if error != nil {
3030
return
3131
}
32-
guard var pixelBuffer = buffer else { return }
33-
32+
guard let pixelBuffer = buffer else { return }
33+
3434
let currentTimestamp = CACurrentMediaTime()
3535
if (currentTimestamp - strongSelf.prevTimestampMs) * 1000 <= strongSelf.delayMs { return }
3636
strongSelf.prevTimestampMs = currentTimestamp
37+
38+
// UnsafeMutablePointer() doesn't guarantee that the converted pointer points to the memory that is still being allocated
39+
// So we create a new pointer and copy the &pixelBuffer's memory to where it points to
40+
let copiedBufferPtr = UnsafeMutablePointer<Float>.allocate(capacity: pixelBuffer.count)
41+
copiedBufferPtr.initialize(from: pixelBuffer, count: pixelBuffer.count)
42+
3743
let startTime = CACurrentMediaTime()
38-
guard let outputs = self?.inferencer.module.detect(image: &pixelBuffer) else {
44+
guard let outputs = self?.inferencer.module.detect(image: copiedBufferPtr) else {
45+
copiedBufferPtr.deallocate()
3946
return
4047
}
48+
copiedBufferPtr.deallocate()
4149
let inferenceTime = CACurrentMediaTime() - startTime
42-
50+
4351
DispatchQueue.main.async {
4452
let ivScaleX : Double = Double(strongSelf.imageViewLive.frame.size.width / CGFloat(PrePostProcessor.inputWidth))
4553
let ivScaleY : Double = Double(strongSelf.imageViewLive.frame.size.height / CGFloat(PrePostProcessor.inputHeight))
4654

4755
let startX = Double((strongSelf.imageViewLive.frame.size.width - CGFloat(ivScaleX) * CGFloat(PrePostProcessor.inputWidth))/2)
4856
let startY = Double((strongSelf.imageViewLive.frame.size.height - CGFloat(ivScaleY) * CGFloat(PrePostProcessor.inputHeight))/2)
49-
57+
5058
let nmsPredictions = PrePostProcessor.outputsToNMSPredictions(outputs: outputs, imgScaleX: 1.0, imgScaleY: 1.0, ivScaleX: ivScaleX, ivScaleY: ivScaleY, startX: startX, startY: startY)
5159

5260
PrePostProcessor.cleanDetection(imageView: strongSelf.imageViewLive)
5361
strongSelf.indicator.isHidden = true
5462
strongSelf.benchmarkLabel.isHidden = false
5563
strongSelf.benchmarkLabel.text = String(format: "%.2fms", 1000*inferenceTime)
56-
64+
5765
PrePostProcessor.showDetection(imageView: strongSelf.imageViewLive, nmsPredictions: nmsPredictions, classes: strongSelf.inferencer.classes)
5866
}
5967
}

0 commit comments

Comments
 (0)