Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions lib/screens/receive/widgets/qr_address_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,20 @@ class QRAddressWidget extends StatelessWidget {
TextSpan(
children: [
TextSpan(
text: subtitle.substring(0, 6),
text: _slice(subtitle, 0, 6),
style: const TextStyle(fontWeight: .bold),
),
const TextSpan(text: ' '),
TextSpan(
text: subtitle.substring(6, 21),
text: _slice(subtitle, 6, 21),
),
const TextSpan(text: '\n'),
TextSpan(
text: subtitle.substring(21, 36),
text: _slice(subtitle, 21, 36),
),
const TextSpan(text: ' '),
TextSpan(
text: subtitle.substring(36),
text: _slice(subtitle, 36),
style: const TextStyle(fontWeight: .bold),
),
],
Expand All @@ -72,4 +72,14 @@ class QRAddressWidget extends StatelessWidget {
);

Future<void> _copyToClipboard() => Clipboard.setData(ClipboardData(text: subtitle));

// Length-safe slice: a full 0x-address is grouped into fixed chunks, but a
// short or empty address must not crash with a RangeError (issue #657 P6 —
// this widget renders on both Receive and Settings). Clamps the bounds to
// the string length instead of slicing past the end.
static String _slice(String value, int start, [int? end]) {
if (start >= value.length) return '';
final clampedEnd = end == null || end > value.length ? value.length : end;
return value.substring(start, clampedEnd);
}
}
19 changes: 19 additions & 0 deletions test/screens/receive/widgets/qr_address_widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,24 @@ void main() {
await tester.tap(find.byType(InkWell));
await tester.pump();
});

testWidgets(
'renders a short/unexpected address without a RangeError '
'(issue #657 P6 regression)', (tester) async {
// A too-short subtitle used to crash on the fixed-index substring(6, 21)
// etc. — it must now render gracefully on Receive and Settings.
await tester.pumpWidget(_host(
const QRAddressWidget(uri: '', subtitle: '0x1234'),
));

expect(tester.takeException(), isNull);
expect(find.textContaining('0x1234'), findsAtLeastNWidgets(1));

// The extreme case: an empty address must also not throw.
await tester.pumpWidget(_host(
const QRAddressWidget(uri: '', subtitle: ''),
));
expect(tester.takeException(), isNull);
});
});
}
Loading