Skip to content

[flutter_markdown] Invalid double parsing image URL in flutter_markdown #146739

Closed
flutter/packages
#6518

Description

@collinjackson

Steps to reproduce

In the example project for flutter_markdown, go to minimal_markdown_demo.dart. Change the value of _data to '![Flutter logo](https://storage.googleapis.com/cms-storage-bucket/0dbfcc7a59cd1cf16282.png#100x)' (or replace the file with the code sample below). Then run the project (on any platform).

Related issue: FlutterFlow/flutterflow-issues#2581

Why this matters: Markdown is often dynamic, user provided content. A malicious user could render an app unusable in places where their content appears.

Expected results

It should render a square Flutter logo with a width of 100.

Actual results

Invalid double error, preventing the page from rendering. This is caused by parsing an empty string as a double. See stack trace below.

Code sample

Code sample

Overwrite minimal_markdown_demo.dart with the following:

import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import '../shared/markdown_demo_widget.dart';

// ignore_for_file: public_member_api_docs

const String _data = '''
![Flutter logo](https://storage.googleapis.com/cms-storage-bucket/0dbfcc7a59cd1cf16282.png#x200)''';

class MinimalMarkdownDemo extends StatelessWidget
    implements MarkdownDemoWidget {
  const MinimalMarkdownDemo({super.key});

  static const String _title = 'Double Parse Crash';

  @override
  String get title => MinimalMarkdownDemo._title;

  @override
  String get description => 'Double Parse Crash example.';

  @override
  Future<String> get data => Future<String>.value(_data);

  @override
  Future<String> get notes => Future<String>.value('');

  @override
  Widget build(BuildContext context) {
    return const Markdown(
      data: _data,
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration Actual: ![Screenshot 2024-04-14 at 10 10 09 AM](https://github.com/flutter/flutter/assets/394889/649f32de-4344-491a-9fba-4acbde5cb116) Expected: ![Screenshot 2024-04-14 at 10 11 12 AM](https://github.com/flutter/flutter/assets/394889/d2318cb4-58fe-40b0-837a-b6266f3457c7)

Logs

Logs
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following FormatException was thrown building MinimalMarkdownDemo:
Invalid double

The relevant error-causing widget was:
  MinimalMarkdownDemo
  MinimalMarkdownDemo:file:///Users/jackson/repos/packages/packages/flutter_markdown/example/lib/screens/home_screen.dart:25:11

When the exception was thrown, this was the stack:
#0      double.parse (dart:core-patch/double_patch.dart:112:28)
#1      MarkdownBuilder._buildImage (package:flutter_markdown/src/builder.dart:572:25)
#2      MarkdownBuilder.visitElementAfter (package:flutter_markdown/src/builder.dart:494:11)
#3      Element.accept (package:markdown/src/ast.dart:53:15)
#4      Element.accept (package:markdown/src/ast.dart:50:17)
#5      MarkdownBuilder.build (package:flutter_markdown/src/builder.dart:203:12)
#6      _MarkdownWidgetState._parseMarkdown (package:flutter_markdown/src/widget.dart:382:25)
#7      _MarkdownWidgetState.didChangeDependencies (package:flutter_markdown/src/widget.dart:325:5)
#8      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5629:11)
#9      ComponentElement.mount (package:flutter/src/widgets/framework.dart:5456:5)
...     Normal element mounting (71 frames)
#80     Element.inflateWidget (package:flutter/src/widgets/framework.dart:4335:16)
#81     Element.updateChild (package:flutter/src/widgets/framework.dart:3846:18)
#82     SliverMultiBoxAdaptorElement.updateChild (package:flutter/src/widgets/sliver.dart:858:37)
#83     SliverMultiBoxAdaptorElement.createChild.<anonymous closure> (package:flutter/src/widgets/sliver.dart:843:20)
#84     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2844:19)
#85     SliverMultiBoxAdaptorElement.createChild (package:flutter/src/widgets/sliver.dart:835:12)
#86     RenderSliverMultiBoxAdaptor._createOrObtainChild.<anonymous closure> (package:flutter/src/rendering/sliver_multi_box_adaptor.dart:349:23)
#87     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:2686:59)
#88     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1097:15)
#89     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2686:14)
#90     RenderSliverMultiBoxAdaptor._createOrObtainChild (package:flutter/src/rendering/sliver_multi_box_adaptor.dart:338:5)
#91     RenderSliverMultiBoxAdaptor.addInitialChild (package:flutter/src/rendering/sliver_multi_box_adaptor.dart:424:5)
#92     RenderSliverFixedExtentBoxAdaptor.performLayout (package:flutter/src/rendering/sliver_fixed_extent_list.dart:274:12)
#93     RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#94     RenderSliverEdgeInsetsPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:139:12)
#95     _RenderSliverFractionalPadding.performLayout (package:flutter/src/widgets/sliver_fill.dart:160:11)
#96     RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#97     RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:601:13)
#98     RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:1555:12)
#99     RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:1464:20)
#100    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#101    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#102    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#103    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#104    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#105    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#106    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#107    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#108    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#109    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#110    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#111    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#112    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#113    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#114    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#115    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#116    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#117    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#118    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#119    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#120    MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:173:12)
#121    _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1063:7)
#122    MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:237:7)
#123    RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:404:14)
#124    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#125    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#126    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#127    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#128    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#129    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#130    _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1440:11)
#131    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#132    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#133    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#134    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#135    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#136    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#137    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#138    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#139    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#140    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#141    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#142    ChildLayoutHelper.layoutChild (package:flutter/src/rendering/layout_helper.dart:52:11)
#143    RenderStack._computeSize (package:flutter/src/rendering/stack.dart:582:43)
#144    RenderStack.performLayout (package:flutter/src/rendering/stack.dart:609:12)
#145    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#146    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#147    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#148    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#149    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#150    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#151    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#152    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#153    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#154    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#155    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#156    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#157    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#158    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#159    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#160    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#161    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#162    RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3726:14)
#163    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#164    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#165    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:21)
#166    RenderObject.layout (package:flutter/src/rendering/object.dart:2575:7)
#167    RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
#168    _RenderTheaterMixin.layoutChild (package:flutter/src/widgets/overlay.dart:968:13)
#169    _RenderTheater.performLayout (package:flutter/src/widgets/overlay.dart:1282:9)
#170    RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2414:7)
#171    PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1051:18)
#172    PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1064:15)
#173    RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:582:23)
#174    WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:991:13)
#175    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:448:5)
#176    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1386:15)
#177    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1311:9)
#178    SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1169:5)
#179    _invoke (dart:ui/hooks.dart:312:13)
#180    PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:399:5)
#181    _drawFrame (dart:ui/hooks.dart:283:31)

════════════════════════════════════════════════════════════════════════════════════════════════════


Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.19.3, on macOS 14.4.1 23E224 darwin-arm64, locale en-US)
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 15.3)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.1)
[✓] IntelliJ IDEA Ultimate Edition (version 2023.3.4)
[✓] VS Code (version 1.88.0)
[✓] Connected device (4 available)
    ! Error: Browsing on the local area network for Collin’s iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local area
      network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources

! Doctor found issues in 1 category.

Activity

  1. github-actions commented on Apr 28, 2024

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  2. locked as resolved and limited conversation to collaborators on Apr 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions