Skip to content

Commit d93d223

Browse files
Fix heap-buffer overflow from FPRDecodeString (#8631)
* Use trimmedURLString for logging * Update CHANGELOG.md * Move nanopb decode methods to test util * Update Package.swift * Incorporate comments
1 parent 11b1a35 commit d93d223

File tree

8 files changed

+81
-71
lines changed

8 files changed

+81
-71
lines changed

FirebasePerformance/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Pending
22
* Create a random number of delay for remote config fetch during app starts.
3-
* Fix log spamming when Firebase Performance is disabled. (#8423)
3+
* Fix log spamming when Firebase Performance is disabled. (#8423, #8577)
4+
* Fix heap-heap-buffer overflow when decoding strings. (#8628)
45

56
# Version 8.6.1
67
* Fix the case where the event were dropped for missing a critical field in the event.

FirebasePerformance/Sources/FPRClient.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ - (void)logNetworkTrace:(nonnull FPRNetworkTrace *)trace {
219219
: @"UNKNOWN";
220220
FPRLogInfo(kFPRClientMetricLogged,
221221
@"Logging network request trace - %@, Response code: %@, %.4fms",
222-
FPRDecodeString(networkRequestMetric.url), responseCode, duration / 1000.0);
222+
trace.trimmedURLString, responseCode, duration / 1000.0);
223223
firebase_perf_v1_PerfMetric metric = FPRGetPerfMetricMessage(self.config.appID);
224224
FPRSetNetworkRequestMetric(&metric, networkRequestMetric);
225225
FPRSetApplicationProcessState(&metric,

FirebasePerformance/Sources/FPRNanoPbUtils.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,30 +53,6 @@ extern pb_bytes_array_t* _Nullable FPREncodeData(NSData* _Nonnull data);
5353
*/
5454
extern pb_bytes_array_t* _Nullable FPREncodeString(NSString* _Nonnull string);
5555

56-
/** Creates a NSData object by copying the given bytes array and returns the reference.
57-
*
58-
* @param pbData The pbData to dedoded as NSData
59-
* @return A reference to NSData
60-
*/
61-
extern NSData* _Nullable FPRDecodeData(pb_bytes_array_t* _Nonnull pbData);
62-
63-
/** Creates a NSString object by copying the given bytes array and returns the reference.
64-
*
65-
* @param pbData The pbData to dedoded as NSString
66-
* @return A reference to the NSString
67-
*/
68-
extern NSString* _Nullable FPRDecodeString(pb_bytes_array_t* _Nonnull pbData);
69-
70-
/** Creates a NSDictionary by copying the given bytes from the StringToStringMap object and returns
71-
* the reference.
72-
*
73-
* @param map The reference to a StringToStringMap object to be decoded.
74-
* @param count The number of entries in the dictionary.
75-
* @return A reference to the dictionary
76-
*/
77-
extern NSDictionary<NSString*, NSString*>* _Nullable FPRDecodeStringToStringMap(
78-
StringToStringMap* _Nullable map, NSInteger count);
79-
8056
/** Callocs a nanopb StringToStringMap and copies the given NSDictionary bytes into the
8157
* StringToStringMap.
8258
*
@@ -85,16 +61,6 @@ extern NSDictionary<NSString*, NSString*>* _Nullable FPRDecodeStringToStringMap(
8561
*/
8662
extern StringToStringMap* _Nullable FPREncodeStringToStringMap(NSDictionary* _Nullable dict);
8763

88-
/** Creates a NSDictionary by copying the given bytes from the StringToNumberMap object and returns
89-
* the reference.
90-
*
91-
* @param map The reference to a StringToNumberMap object to be decoded.
92-
* @param count The number of entries in the dictionary.
93-
* @return A reference to the dictionary
94-
*/
95-
extern NSDictionary<NSString*, NSNumber*>* _Nullable FPRDecodeStringToNumberMap(
96-
StringToNumberMap* _Nullable map, NSInteger count);
97-
9864
/** Callocs a nanopb StringToNumberMap and copies the given NSDictionary bytes into the
9965
* StringToStringMap.
10066
*

FirebasePerformance/Sources/FPRNanoPbUtils.m

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,6 @@ static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkTy
150150
return FPREncodeData(stringBytes);
151151
}
152152

153-
NSData *FPRDecodeData(pb_bytes_array_t *pbData) {
154-
NSData *data = [NSData dataWithBytes:&(pbData->bytes) length:pbData->size];
155-
return data;
156-
}
157-
158-
NSString *FPRDecodeString(pb_bytes_array_t *pbData) {
159-
NSData *data = FPRDecodeData(pbData);
160-
return [NSString stringWithCString:[data bytes] encoding:NSUTF8StringEncoding];
161-
}
162-
163153
StringToStringMap *_Nullable FPREncodeStringToStringMap(NSDictionary *_Nullable dict) {
164154
StringToStringMap *map = calloc(dict.count, sizeof(StringToStringMap));
165155
__block NSUInteger index = 0;
@@ -171,17 +161,6 @@ static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkTy
171161
return map;
172162
}
173163

174-
NSDictionary<NSString *, NSString *> *FPRDecodeStringToStringMap(StringToStringMap *map,
175-
NSInteger count) {
176-
NSMutableDictionary<NSString *, NSString *> *dict = [[NSMutableDictionary alloc] init];
177-
for (int i = 0; i < count; i++) {
178-
NSString *key = FPRDecodeString(map[i].key);
179-
NSString *value = FPRDecodeString(map[i].value);
180-
dict[key] = value;
181-
}
182-
return [dict copy];
183-
}
184-
185164
StringToNumberMap *_Nullable FPREncodeStringToNumberMap(NSDictionary *_Nullable dict) {
186165
StringToNumberMap *map = calloc(dict.count, sizeof(StringToNumberMap));
187166
__block NSUInteger index = 0;
@@ -194,19 +173,6 @@ static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkTy
194173
return map;
195174
}
196175

197-
NSDictionary<NSString *, NSNumber *> *_Nullable FPRDecodeStringToNumberMap(
198-
StringToNumberMap *_Nullable map, NSInteger count) {
199-
NSMutableDictionary<NSString *, NSNumber *> *dict = [[NSMutableDictionary alloc] init];
200-
for (int i = 0; i < count; i++) {
201-
if (map[i].has_value) {
202-
NSString *key = FPRDecodeString(map[i].key);
203-
NSNumber *value = [NSNumber numberWithLongLong:map[i].value];
204-
dict[key] = value;
205-
}
206-
}
207-
return [dict copy];
208-
}
209-
210176
firebase_perf_v1_PerfSession *FPREncodePerfSessions(NSArray<FPRSessionDetails *> *sessions,
211177
NSInteger count) {
212178
firebase_perf_v1_PerfSession *perfSessions = calloc(count, sizeof(firebase_perf_v1_PerfSession));

FirebasePerformance/Tests/Unit/FPRNanoPbUtilsTest.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h"
3030

3131
#import "FirebasePerformance/Tests/Unit/FPRTestCase.h"
32+
#import "FirebasePerformance/Tests/Unit/FPRTestUtils.h"
3233

3334
#import <OCMock/OCMock.h>
3435

FirebasePerformance/Tests/Unit/FPRTestUtils.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#import <Foundation/Foundation.h>
1616

17+
#import "FirebasePerformance/Sources/FPRNanoPbUtils.h"
1718
#import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
1819
#import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
1920

@@ -65,6 +66,41 @@ NS_ASSUME_NONNULL_BEGIN
6566
/** Creates a random GDTCOREvent object with network event. */
6667
+ (GDTCOREvent *)createRandomNetworkGDTEvent:(NSString *)url;
6768

69+
/** Creates a NSData object by copying the given bytes array and returns the reference.
70+
*
71+
* @param pbData The pbData to dedoded as NSData
72+
* @return A reference to NSData
73+
*/
74+
extern NSData *_Nullable FPRDecodeData(pb_bytes_array_t *_Nonnull pbData);
75+
76+
/** Creates a NSString object by copying the given bytes array and returns the reference.
77+
*
78+
* @param pbData The pbData to dedoded as NSString
79+
* @return A reference to the NSString
80+
* @note This method may cause heap-buffer overflow
81+
*/
82+
extern NSString *_Nullable FPRDecodeString(pb_bytes_array_t *_Nonnull pbData);
83+
84+
/** Creates a NSDictionary by copying the given bytes from the StringToStringMap object and returns
85+
* the reference.
86+
*
87+
* @param map The reference to a StringToStringMap object to be decoded.
88+
* @param count The number of entries in the dictionary.
89+
* @return A reference to the dictionary
90+
*/
91+
extern NSDictionary<NSString *, NSString *> *_Nullable FPRDecodeStringToStringMap(
92+
StringToStringMap *_Nullable map, NSInteger count);
93+
94+
/** Creates a NSDictionary by copying the given bytes from the StringToNumberMap object and returns
95+
* the reference.
96+
*
97+
* @param map The reference to a StringToNumberMap object to be decoded.
98+
* @param count The number of entries in the dictionary.
99+
* @return A reference to the dictionary
100+
*/
101+
extern NSDictionary<NSString *, NSNumber *> *_Nullable FPRDecodeStringToNumberMap(
102+
StringToNumberMap *_Nullable map, NSInteger count);
103+
68104
@end
69105

70106
NS_ASSUME_NONNULL_END

FirebasePerformance/Tests/Unit/FPRTestUtils.m

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
@implementation FPRTestUtils
2929

30-
#pragma mark - Test utility methods
30+
#pragma mark - Retrieve bundle
3131

3232
+ (NSBundle *)getBundle {
3333
#if SWIFT_PACKAGE
@@ -37,6 +37,7 @@ + (NSBundle *)getBundle {
3737
#endif
3838
}
3939

40+
#pragma mark - Create events and PerfMetrics
4041
+ (FIRTrace *)createRandomTraceWithName:(NSString *)traceName {
4142
FIRTrace *trace = [[FIRTrace alloc] initWithName:traceName];
4243
[trace start];
@@ -153,4 +154,40 @@ + (GDTCOREvent *)createRandomNetworkGDTEvent:(NSString *)url {
153154
return gdtEvent;
154155
}
155156

157+
#pragma mark - Decode nanoPb pbData
158+
159+
NSData *FPRDecodeData(pb_bytes_array_t *pbData) {
160+
NSData *data = [NSData dataWithBytes:&(pbData->bytes) length:pbData->size];
161+
return data;
162+
}
163+
164+
NSString *FPRDecodeString(pb_bytes_array_t *pbData) {
165+
NSData *data = FPRDecodeData(pbData);
166+
return [NSString stringWithCString:[data bytes] encoding:NSUTF8StringEncoding];
167+
}
168+
169+
NSDictionary<NSString *, NSString *> *FPRDecodeStringToStringMap(StringToStringMap *map,
170+
NSInteger count) {
171+
NSMutableDictionary<NSString *, NSString *> *dict = [[NSMutableDictionary alloc] init];
172+
for (int i = 0; i < count; i++) {
173+
NSString *key = FPRDecodeString(map[i].key);
174+
NSString *value = FPRDecodeString(map[i].value);
175+
dict[key] = value;
176+
}
177+
return [dict copy];
178+
}
179+
180+
NSDictionary<NSString *, NSNumber *> *_Nullable FPRDecodeStringToNumberMap(
181+
StringToNumberMap *_Nullable map, NSInteger count) {
182+
NSMutableDictionary<NSString *, NSNumber *> *dict = [[NSMutableDictionary alloc] init];
183+
for (int i = 0; i < count; i++) {
184+
if (map[i].has_value) {
185+
NSString *key = FPRDecodeString(map[i].key);
186+
NSNumber *value = [NSNumber numberWithLongLong:map[i].value];
187+
dict[key] = value;
188+
}
189+
}
190+
return [dict copy];
191+
}
192+
156193
@end

Package.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,9 @@ let package = Package(
893893
],
894894
cSettings: [
895895
.headerSearchPath("../../.."),
896+
.define("PB_FIELD_32BIT", to: "1"),
897+
.define("PB_NO_PACKED_STRUCTS", to: "1"),
898+
.define("PB_ENABLE_MALLOC", to: "1"),
896899
]
897900
),
898901

0 commit comments

Comments
 (0)