Fix `RangeError` hazards in links (dart-lang/markdown#624)

diff --git a/pkgs/markdown/CHANGELOG.md b/pkgs/markdown/CHANGELOG.md
index ec5b890..658d8b6 100644
--- a/pkgs/markdown/CHANGELOG.md
+++ b/pkgs/markdown/CHANGELOG.md
@@ -2,6 +2,7 @@
 
 * Fix an issue with checkbox list items separated with blank lines (#602).
 * Require package `web: '>=0.4.2 <2.0.0'`.
+* Fix several `RangeError` hazards in links (#623).
 
 ## 7.2.2
 
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/link_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/link_syntax.dart
index 7b3c304..bca3efb 100644
--- a/pkgs/markdown/lib/src/inline_syntaxes/link_syntax.dart
+++ b/pkgs/markdown/lib/src/inline_syntaxes/link_syntax.dart
@@ -216,6 +216,7 @@
       final char = parser.charAt(parser.pos);
       if (char == $backslash) {
         parser.advanceBy(1);
+        if (parser.isDone) return null;
         final next = parser.charAt(parser.pos);
         if (next != $backslash && next != $rbracket) {
           buffer.writeCharCode(char);
@@ -273,12 +274,14 @@
   /// Returns the link if it was successfully created, `null` otherwise.
   InlineLink? _parseInlineBracketedLink(InlineParser parser) {
     parser.advanceBy(1);
+    if (parser.isDone) return null;
 
     final buffer = StringBuffer();
     while (true) {
       final char = parser.charAt(parser.pos);
       if (char == $backslash) {
         parser.advanceBy(1);
+        if (parser.isDone) return null;
         final next = parser.charAt(parser.pos);
         // TODO: Follow the backslash spec better here.
         // https://spec.commonmark.org/0.30/#backslash-escapes
@@ -302,6 +305,7 @@
     final destination = buffer.toString();
 
     parser.advanceBy(1);
+    if (parser.isDone) return null;
     final char = parser.charAt(parser.pos);
     if (char == $space || char == $lf || char == $cr || char == $ff) {
       final title = _parseTitle(parser);
@@ -433,6 +437,7 @@
 
     final closeDelimiter = delimiter == $lparen ? $rparen : delimiter;
     parser.advanceBy(1);
+    if (parser.isDone) return null;
 
     // Now we look for an un-escaped closing delimiter.
     final buffer = StringBuffer();
@@ -440,6 +445,7 @@
       final char = parser.charAt(parser.pos);
       if (char == $backslash) {
         parser.advanceBy(1);
+        if (parser.isDone) return null;
         final next = parser.charAt(parser.pos);
         if (next != $backslash && next != closeDelimiter) {
           buffer.writeCharCode(char);
diff --git a/pkgs/markdown/test/markdown_test.dart b/pkgs/markdown/test/markdown_test.dart
index 1fea683..feb2d77 100644
--- a/pkgs/markdown/test/markdown_test.dart
+++ b/pkgs/markdown/test/markdown_test.dart
@@ -80,6 +80,42 @@
 <p>5 Ethernet ([Music](</p>
 ''');
 
+    validateCore('Incorrect Links - Issue #623 - 1 - Bracketed link 1', '''
+[](<
+''', '''
+<p>[](&lt;</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 2 - Bracketed link 2', '''
+[](<>
+''', '''
+<p>[](&lt;&gt;</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 3 - Bracketed link 3', r'''
+[](<\
+''', r'''
+<p>[](&lt;\</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 4 - Link title 1', '''
+[](www.example.com "
+''', '''
+<p>[](www.example.com &quot;</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 5 - Link title 2', r'''
+[](www.example.com "\
+''', r'''
+<p>[](www.example.com &quot;\</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 6 - Reference link label', r'''
+[][\
+''', r'''
+<p>[][\</p>
+''');
+
     validateCore('Escaping code block language', '''
 ```"/><a/href="url">arbitrary_html</a>
 ```