react-native-ble-manager 12.4.4 → 12.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -460,6 +460,15 @@ public class BleManager extends NativeBleManagerSpec {
460
460
  callback.invoke("ServiceUUID and characteristicUUID required.");
461
461
  return;
462
462
  }
463
+ // Validate UUID formats to prevent crash
464
+ if (!UUIDHelper.isValidBLEUUID(serviceUUID)) {
465
+ callback.invoke("Invalid service UUID format: " + serviceUUID);
466
+ return;
467
+ }
468
+ if (!UUIDHelper.isValidBLEUUID(characteristicUUID)) {
469
+ callback.invoke("Invalid characteristic UUID format: " + characteristicUUID);
470
+ return;
471
+ }
463
472
  Peripheral peripheral = peripherals.get(deviceUUID);
464
473
  if (peripheral != null) {
465
474
  peripheral.registerNotify(UUIDHelper.uuidFromString(serviceUUID),
@@ -475,6 +484,15 @@ public class BleManager extends NativeBleManagerSpec {
475
484
  callback.invoke("ServiceUUID and characteristicUUID required.");
476
485
  return;
477
486
  }
487
+ // Validate UUID formats to prevent crash
488
+ if (!UUIDHelper.isValidBLEUUID(serviceUUID)) {
489
+ callback.invoke("Invalid service UUID format: " + serviceUUID);
490
+ return;
491
+ }
492
+ if (!UUIDHelper.isValidBLEUUID(characteristicUUID)) {
493
+ callback.invoke("Invalid characteristic UUID format: " + characteristicUUID);
494
+ return;
495
+ }
478
496
  Peripheral peripheral = peripherals.get(deviceUUID);
479
497
  if (peripheral != null) {
480
498
  if (peripheral.isConnected()) {
@@ -494,6 +512,15 @@ public class BleManager extends NativeBleManagerSpec {
494
512
  callback.invoke("ServiceUUID and characteristicUUID required.");
495
513
  return;
496
514
  }
515
+ // Validate UUID formats to prevent crash
516
+ if (!UUIDHelper.isValidBLEUUID(serviceUUID)) {
517
+ callback.invoke("Invalid service UUID format: " + serviceUUID);
518
+ return;
519
+ }
520
+ if (!UUIDHelper.isValidBLEUUID(characteristicUUID)) {
521
+ callback.invoke("Invalid characteristic UUID format: " + characteristicUUID);
522
+ return;
523
+ }
497
524
  Peripheral peripheral = peripherals.get(deviceUUID);
498
525
  if (peripheral != null) {
499
526
  if (peripheral.isConnected()) {
@@ -514,6 +541,15 @@ public class BleManager extends NativeBleManagerSpec {
514
541
  callback.invoke("ServiceUUID and characteristicUUID required.");
515
542
  return;
516
543
  }
544
+ // Validate UUID formats to prevent crash
545
+ if (!UUIDHelper.isValidBLEUUID(serviceUUID)) {
546
+ callback.invoke("Invalid service UUID format: " + serviceUUID);
547
+ return;
548
+ }
549
+ if (!UUIDHelper.isValidBLEUUID(characteristicUUID)) {
550
+ callback.invoke("Invalid characteristic UUID format: " + characteristicUUID);
551
+ return;
552
+ }
517
553
  Peripheral peripheral = peripherals.get(deviceUUID);
518
554
  if (peripheral != null) {
519
555
  if (peripheral.isConnected()) {
@@ -539,6 +575,15 @@ public class BleManager extends NativeBleManagerSpec {
539
575
  callback.invoke("ServiceUUID and characteristicUUID required.");
540
576
  return;
541
577
  }
578
+ // Validate UUID formats to prevent crash
579
+ if (!UUIDHelper.isValidBLEUUID(serviceUUID)) {
580
+ callback.invoke("Invalid service UUID format: " + serviceUUID);
581
+ return;
582
+ }
583
+ if (!UUIDHelper.isValidBLEUUID(characteristicUUID)) {
584
+ callback.invoke("Invalid characteristic UUID format: " + characteristicUUID);
585
+ return;
586
+ }
542
587
  Peripheral peripheral = peripherals.get(deviceUUID);
543
588
  if (peripheral != null) {
544
589
  if (peripheral.isConnected()) {
@@ -563,6 +608,15 @@ public class BleManager extends NativeBleManagerSpec {
563
608
  callback.invoke("ServiceUUID and characteristicUUID required.");
564
609
  return;
565
610
  }
611
+ // Validate UUID formats to prevent crash
612
+ if (!UUIDHelper.isValidBLEUUID(serviceUUID)) {
613
+ callback.invoke("Invalid service UUID format: " + serviceUUID);
614
+ return;
615
+ }
616
+ if (!UUIDHelper.isValidBLEUUID(characteristicUUID)) {
617
+ callback.invoke("Invalid characteristic UUID format: " + characteristicUUID);
618
+ return;
619
+ }
566
620
  Peripheral peripheral = peripherals.get(deviceUUID);
567
621
  if (peripheral != null) {
568
622
  if (peripheral.isConnected()) {
@@ -582,6 +636,19 @@ public class BleManager extends NativeBleManagerSpec {
582
636
  callback.invoke("ServiceUUID, CharacteristicUUID and descriptorUUID required.", null);
583
637
  return;
584
638
  }
639
+ // Validate UUID formats to prevent crash
640
+ if (!UUIDHelper.isValidBLEUUID(serviceUUID)) {
641
+ callback.invoke("Invalid service UUID format: " + serviceUUID, null);
642
+ return;
643
+ }
644
+ if (!UUIDHelper.isValidBLEUUID(characteristicUUID)) {
645
+ callback.invoke("Invalid characteristic UUID format: " + characteristicUUID, null);
646
+ return;
647
+ }
648
+ if (!UUIDHelper.isValidBLEUUID(descriptorUUID)) {
649
+ callback.invoke("Invalid descriptor UUID format: " + descriptorUUID, null);
650
+ return;
651
+ }
585
652
 
586
653
  Peripheral peripheral = peripherals.get(deviceUUID);
587
654
  if (peripheral == null) {
@@ -604,6 +671,19 @@ public class BleManager extends NativeBleManagerSpec {
604
671
  callback.invoke("ServiceUUID, CharacteristicUUID and descriptorUUID required.", null);
605
672
  return;
606
673
  }
674
+ // Validate UUID formats to prevent crash
675
+ if (!UUIDHelper.isValidBLEUUID(serviceUUID)) {
676
+ callback.invoke("Invalid service UUID format: " + serviceUUID, null);
677
+ return;
678
+ }
679
+ if (!UUIDHelper.isValidBLEUUID(characteristicUUID)) {
680
+ callback.invoke("Invalid characteristic UUID format: " + characteristicUUID, null);
681
+ return;
682
+ }
683
+ if (!UUIDHelper.isValidBLEUUID(descriptorUUID)) {
684
+ callback.invoke("Invalid descriptor UUID format: " + descriptorUUID, null);
685
+ return;
686
+ }
607
687
 
608
688
  Peripheral peripheral = peripherals.get(deviceUUID);
609
689
  if (peripheral == null) {
@@ -109,9 +109,17 @@ public class CompanionScanner {
109
109
  AssociationRequest.Builder builder = new AssociationRequest.Builder()
110
110
  .setSingleDevice(options.hasKey("single") && options.getBoolean("single")) ;
111
111
 
112
+ int validUUIDCount = 0;
112
113
  for (int i = 0; i < serviceUUIDs.size(); i++) {
113
- final ParcelUuid uuid = new ParcelUuid(UUIDHelper.uuidFromString(serviceUUIDs.getString(i)));
114
+ String uuidString = serviceUUIDs.getString(i);
115
+ // Validate UUID format to prevent crash
116
+ if (!UUIDHelper.isValidBLEUUID(uuidString)) {
117
+ Log.w(LOG_TAG, "Warning: Invalid UUID format in scan options: " + uuidString + ", skipping");
118
+ continue;
119
+ }
120
+ final ParcelUuid uuid = new ParcelUuid(UUIDHelper.uuidFromString(uuidString));
114
121
  Log.d(LOG_TAG, "Filter service: " + uuid);
122
+ validUUIDCount++;
115
123
 
116
124
  builder = builder
117
125
  // Add LE filter.
@@ -119,6 +127,12 @@ public class CompanionScanner {
119
127
  .setScanFilter(new ScanFilter.Builder().setServiceUuid(uuid).build())
120
128
  .build());
121
129
  }
130
+
131
+ // If serviceUUIDs were provided but none were valid, return error
132
+ if (serviceUUIDs.size() > 0 && validUUIDCount == 0) {
133
+ callback.invoke("Invalid UUID format in serviceUUIDs: all UUIDs are invalid");
134
+ return;
135
+ }
122
136
 
123
137
  AssociationRequest pairingRequest = builder.build();
124
138
  if (scanCallback != null) {
@@ -104,10 +104,23 @@ public class DefaultScanManager extends ScanManager {
104
104
 
105
105
  ReadableArray serviceUUIDs = options.getArray("serviceUUIDs");
106
106
  if (serviceUUIDs != null && serviceUUIDs.size() > 0) {
107
+ int validUUIDCount = 0;
107
108
  for (int i = 0; i < serviceUUIDs.size(); i++) {
108
- ScanFilter filter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUIDHelper.uuidFromString(Objects.requireNonNull(serviceUUIDs.getString(i))))).build();
109
+ String uuidString = Objects.requireNonNull(serviceUUIDs.getString(i));
110
+ // Validate UUID format to prevent crash
111
+ if (!UUIDHelper.isValidBLEUUID(uuidString)) {
112
+ Log.w(BleManager.LOG_TAG, "Warning: Invalid UUID format in scan options: " + uuidString + ", skipping");
113
+ continue;
114
+ }
115
+ ScanFilter filter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUIDHelper.uuidFromString(uuidString))).build();
109
116
  filters.add(filter);
110
- Log.d(BleManager.LOG_TAG, "Filter service: " + serviceUUIDs.getString(i));
117
+ validUUIDCount++;
118
+ Log.d(BleManager.LOG_TAG, "Filter service: " + uuidString);
119
+ }
120
+ // If serviceUUIDs were provided but none were valid, return error
121
+ if (validUUIDCount == 0) {
122
+ callback.invoke("Invalid UUID format in serviceUUIDs: all UUIDs are invalid");
123
+ return;
111
124
  }
112
125
  }
113
126
 
@@ -9,6 +9,27 @@ public class UUIDHelper {
9
9
  // base UUID used to build 128 bit Bluetooth UUIDs
10
10
  public static final String UUID_BASE = "0000XXXX-0000-1000-8000-00805f9b34fb";
11
11
 
12
+ // Validate BLE UUID format (16-bit or 128-bit)
13
+ // Returns true if the string is a valid BLE UUID format
14
+ public static boolean isValidBLEUUID(String uuidString) {
15
+ if (uuidString == null || uuidString.isEmpty()) {
16
+ return false;
17
+ }
18
+
19
+ // Validate 16-bit UUID (4 hex characters)
20
+ if (uuidString.length() == 4) {
21
+ return uuidString.matches("[0-9A-Fa-f]{4}");
22
+ }
23
+
24
+ // Validate 128-bit UUID (standard UUID format)
25
+ try {
26
+ UUID.fromString(uuidString);
27
+ return true;
28
+ } catch (IllegalArgumentException e) {
29
+ return false;
30
+ }
31
+ }
32
+
12
33
  // handle 16 and 128 bit UUIDs
13
34
  public static UUID uuidFromString(String uuid) {
14
35
 
package/ios/Helper.swift CHANGED
@@ -274,6 +274,24 @@ class Helper {
274
274
  return nil // Characteristic not found on this service
275
275
  }
276
276
 
277
+ // Validate BLE UUID format (16-bit or 128-bit)
278
+ // Returns true if the string is a valid BLE UUID format
279
+ static func isValidBLEUUID(_ uuidString: String) -> Bool {
280
+ // Check for empty string
281
+ if uuidString.isEmpty {
282
+ return false
283
+ }
284
+
285
+ // Validate 16-bit UUID (4 hex characters)
286
+ let hexCharacterSet = CharacterSet(charactersIn: "0123456789ABCDEFabcdef")
287
+ let isValid16Bit = uuidString.count == 4 && uuidString.rangeOfCharacter(from: hexCharacterSet.inverted) == nil
288
+
289
+ // Validate 128-bit UUID (standard UUID format)
290
+ let isValid128Bit = UUID(uuidString: uuidString) != nil
291
+
292
+ return isValid16Bit || isValid128Bit
293
+ }
294
+
277
295
  }
278
296
 
279
297
  class Peripheral: Hashable {
@@ -191,6 +191,21 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
191
191
  prop: CBCharacteristicProperties,
192
192
  callback: @escaping RCTResponseSenderBlock
193
193
  ) -> BLECommandContext? {
194
+ // Validate UUID formats to prevent CBUUID(string:) crash
195
+ guard Helper.isValidBLEUUID(serviceUUIDString) else {
196
+ let error = "Invalid service UUID format: \(serviceUUIDString)"
197
+ NSLog(error)
198
+ callback([error])
199
+ return nil
200
+ }
201
+
202
+ guard Helper.isValidBLEUUID(characteristicUUIDString) else {
203
+ let error = "Invalid characteristic UUID format: \(characteristicUUIDString)"
204
+ NSLog(error)
205
+ callback([error])
206
+ return nil
207
+ }
208
+
194
209
  let serviceUUID = CBUUID(string: serviceUUIDString)
195
210
  let characteristicUUID = CBUUID(string: characteristicUUIDString)
196
211
 
@@ -363,7 +378,21 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
363
378
  if let serviceUUIDStrings = scanningOptions["serviceUUIDs"]
364
379
  as? [String]
365
380
  {
366
- serviceUUIDs = serviceUUIDStrings.map { CBUUID(string: $0) }
381
+ // Validate UUID formats to prevent CBUUID(string:) crash
382
+ for uuidString in serviceUUIDStrings {
383
+ if Helper.isValidBLEUUID(uuidString) {
384
+ serviceUUIDs.append(CBUUID(string: uuidString))
385
+ } else {
386
+ NSLog("Warning: Invalid UUID format in scan options: \(uuidString), skipping")
387
+ }
388
+ }
389
+ // If serviceUUIDs were provided but none were valid, return error
390
+ if !serviceUUIDStrings.isEmpty && serviceUUIDs.isEmpty {
391
+ let error = "Invalid UUID format in serviceUUIDs: all UUIDs are invalid"
392
+ NSLog(error)
393
+ callback([error])
394
+ return
395
+ }
367
396
  }
368
397
 
369
398
  var options: [String: Any]?
@@ -528,8 +557,14 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
528
557
 
529
558
  var uuids: [CBUUID] = []
530
559
  for string in services {
531
- let uuid = CBUUID(string: string)
532
- uuids.append(uuid)
560
+ // Validate UUID format to prevent CBUUID(string:) crash
561
+ guard Helper.isValidBLEUUID(string) else {
562
+ let error = "Invalid service UUID format: \(string)"
563
+ NSLog(error)
564
+ callback([error])
565
+ return
566
+ }
567
+ uuids.append(CBUUID(string: string))
533
568
  }
534
569
 
535
570
  if !uuids.isEmpty {
@@ -587,6 +622,14 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
587
622
  let peripheral = context.peripheral
588
623
  let characteristic = context.characteristic
589
624
 
625
+ // Validate UUID format to prevent CBUUID(string:) crash
626
+ guard Helper.isValidBLEUUID(descriptorUUID) else {
627
+ let error = "Invalid descriptor UUID format: \(descriptorUUID)"
628
+ NSLog(error)
629
+ callback([error])
630
+ return
631
+ }
632
+
590
633
  guard
591
634
  let descriptor = Helper.findDescriptor(
592
635
  fromUUID: CBUUID(string: descriptorUUID),
@@ -642,6 +685,14 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
642
685
  let peripheral = context.peripheral
643
686
  let characteristic = context.characteristic
644
687
 
688
+ // Validate UUID format to prevent CBUUID(string:) crash
689
+ guard Helper.isValidBLEUUID(descriptorUUID) else {
690
+ let error = "Invalid descriptor UUID format: \(descriptorUUID)"
691
+ NSLog(error)
692
+ callback([error])
693
+ return
694
+ }
695
+
645
696
  guard
646
697
  let descriptor = Helper.findDescriptor(
647
698
  fromUUID: CBUUID(string: descriptorUUID),
@@ -696,6 +747,15 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
696
747
  var serviceUUIDs: [CBUUID] = []
697
748
 
698
749
  for uuidString in serviceUUIDStrings {
750
+ // Validate BLE UUID format to prevent CBUUID(string:) crash
751
+ guard Helper.isValidBLEUUID(uuidString) else {
752
+ let error = uuidString.isEmpty ? "Invalid UUID: empty string" : "Invalid UUID format: \(uuidString)"
753
+ NSLog(error)
754
+ callback([error])
755
+ return
756
+ }
757
+
758
+ // Create CBUUID only with validated UUID string (prevents crash)
699
759
  serviceUUIDs.append(CBUUID(string: uuidString))
700
760
  }
701
761
 
@@ -1397,6 +1457,11 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
1397
1457
  ) {
1398
1458
  if let error = error {
1399
1459
  NSLog("Error: \(error)")
1460
+ invokeAndClearDictionary(
1461
+ &retrieveServicesCallbacks,
1462
+ withKey: peripheral.uuidAsString(),
1463
+ usingParameters: [error.localizedDescription]
1464
+ )
1400
1465
  return
1401
1466
  }
1402
1467
  if SwiftBleManager.verboseLogging {
@@ -1440,21 +1505,44 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
1440
1505
  ) {
1441
1506
  if let error = error {
1442
1507
  NSLog("Error: \(error)")
1443
- return
1444
1508
  }
1445
1509
  if SwiftBleManager.verboseLogging {
1446
1510
  NSLog("Characteristics For Service Discover")
1447
1511
  }
1448
1512
 
1513
+ let peripheralUUIDString = peripheral.uuidAsString()
1514
+ let characteristics = (error == nil) ? (service.characteristics ?? []) : []
1515
+
1516
+ if characteristics.isEmpty {
1517
+ if var servicesLatch = retrieveServicesLatches[peripheralUUIDString] {
1518
+ servicesLatch.remove(service)
1519
+ retrieveServicesLatches[peripheralUUIDString] = servicesLatch
1520
+
1521
+ if servicesLatch.isEmpty {
1522
+ if let peripheral = peripherals[peripheralUUIDString] {
1523
+ invokeAndClearDictionary(
1524
+ &retrieveServicesCallbacks,
1525
+ withKey: peripheralUUIDString,
1526
+ usingParameters: [
1527
+ NSNull(), peripheral.servicesInfo(),
1528
+ ]
1529
+ )
1530
+ }
1531
+ retrieveServicesLatches.removeValue(
1532
+ forKey: peripheralUUIDString
1533
+ )
1534
+ }
1535
+ }
1536
+ return
1537
+ }
1538
+
1449
1539
  var characteristicsForService = Set<CBCharacteristic>()
1450
- characteristicsForService.formUnion(service.characteristics ?? [])
1540
+ characteristicsForService.formUnion(characteristics)
1451
1541
  characteristicsLatches[service.uuid.uuidString] =
1452
1542
  characteristicsForService
1453
1543
 
1454
- if let characteristics = service.characteristics {
1455
- for characteristic in characteristics {
1456
- peripheral.discoverDescriptors(for: characteristic)
1457
- }
1544
+ for characteristic in characteristics {
1545
+ peripheral.discoverDescriptors(for: characteristic)
1458
1546
  }
1459
1547
  }
1460
1548
 
@@ -1465,7 +1553,6 @@ public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
1465
1553
  ) {
1466
1554
  if let error = error {
1467
1555
  NSLog("Error: \(error)")
1468
- return
1469
1556
  }
1470
1557
  let peripheralUUIDString: String = peripheral.uuidAsString()
1471
1558
  let serviceUUIDString: String =
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-ble-manager",
3
- "version": "12.4.4",
3
+ "version": "12.4.5",
4
4
  "description": "A BLE module for react native.",
5
5
  "homepage": "https://innoveit.github.io/react-native-ble-manager/",
6
6
  "repository": {