mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
fix(mobile): bound and isolate Solo discovery failures
Skip invalid inventory events without losing valid agents, and cancel metadata body reads after a total deadline. Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <klopez4212@gmail.com>
This commit is contained in:
@@ -63,7 +63,12 @@ Map<String, String> _inventoryNames(List<NostrEvent> events, String owner) {
|
||||
final id = event.getTagValue('d');
|
||||
if (id == null || !RegExp(r'^[0-9a-f]{64}$').hasMatch(id)) continue;
|
||||
// Verify before allowing a newer tombstone or record to replace a head.
|
||||
nostr.Event.fromJson(jsonEncode(event.toJson()));
|
||||
try {
|
||||
nostr.Event.fromJson(jsonEncode(event.toJson()));
|
||||
} catch (_) {
|
||||
// A corrupt record must not hide unrelated verified agents.
|
||||
continue;
|
||||
}
|
||||
final previous = heads[id];
|
||||
if (previous == null || meEventIsNewer(event, previous)) heads[id] = event;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:isolate';
|
||||
|
||||
@@ -28,12 +29,24 @@ final meArchivedAgentsProvider = FutureProvider<Set<String>>((ref) async {
|
||||
)
|
||||
.timeout(const Duration(seconds: 3));
|
||||
if (response.statusCode != 200) return {};
|
||||
final chunks = StreamIterator(
|
||||
response.stream.timeout(const Duration(seconds: 3)),
|
||||
);
|
||||
final bytes = <int>[];
|
||||
await for (final chunk in response.stream.timeout(
|
||||
const Duration(seconds: 3),
|
||||
)) {
|
||||
if (bytes.length + chunk.length > 256 * 1024) return {};
|
||||
bytes.addAll(chunk);
|
||||
try {
|
||||
await (() async {
|
||||
while (await chunks.moveNext()) {
|
||||
final chunk = chunks.current;
|
||||
if (bytes.length + chunk.length > 256 * 1024) {
|
||||
throw const FormatException(
|
||||
'Relay information exceeds size limit.',
|
||||
);
|
||||
}
|
||||
bytes.addAll(chunk);
|
||||
}
|
||||
})().timeout(const Duration(seconds: 3));
|
||||
} finally {
|
||||
await chunks.cancel();
|
||||
}
|
||||
sync.check();
|
||||
final info = jsonDecode(utf8.decode(bytes));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:buzz/shared/me/me_archived_agents.dart';
|
||||
@@ -68,6 +69,40 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
test('slow metadata has a total deadline and cancels its stream', () async {
|
||||
final owner = nostr.Keys.generate();
|
||||
final relay = _ArchiveRelay(null);
|
||||
var cancelled = false;
|
||||
final body = StreamController<List<int>>(onCancel: () => cancelled = true);
|
||||
final client = MockClient.streaming(
|
||||
(_, _) async => http.StreamedResponse(body.stream, 200),
|
||||
);
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
meSyncProvider.overrideWithValue(
|
||||
MeSync(
|
||||
relay,
|
||||
RelayConfig(baseUrl: 'https://relay.test', nsec: owner.nsec),
|
||||
),
|
||||
),
|
||||
meRelayInformationClientProvider.overrideWithValue(client),
|
||||
],
|
||||
);
|
||||
addTearDown(container.dispose);
|
||||
addTearDown(client.close);
|
||||
addTearDown(body.close);
|
||||
final trickle = Timer.periodic(const Duration(milliseconds: 100), (_) {
|
||||
body.add([32]);
|
||||
});
|
||||
addTearDown(trickle.cancel);
|
||||
final result = await container
|
||||
.read(meArchivedAgentsProvider.future)
|
||||
.timeout(const Duration(seconds: 5));
|
||||
expect(result, isEmpty);
|
||||
expect(cancelled, isTrue);
|
||||
expect(relay.author, isNull);
|
||||
});
|
||||
|
||||
test(
|
||||
'contact keys and unavailable metadata are not archive authority',
|
||||
() async {
|
||||
|
||||
@@ -237,6 +237,11 @@ void main() {
|
||||
],
|
||||
inventory: [
|
||||
listing(agent.public),
|
||||
for (final field in ['id', 'sig'])
|
||||
NostrEvent.fromJson(
|
||||
listing(agent.public, time: 3, content: '{}').toJson()
|
||||
..[field] = '0' * (field == 'id' ? 64 : 128),
|
||||
),
|
||||
listing(archivedAgent.public),
|
||||
listing(removed.public),
|
||||
listing(removed.public, time: 2, content: '{}'),
|
||||
|
||||
Reference in New Issue
Block a user