Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix browser crashing when searching for a malformed HTML tag #6297

Merged
merged 5 commits into from
Jul 1, 2021
Merged
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
11 changes: 8 additions & 3 deletions src/HtmlUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,14 @@ export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts
try {
if (highlights && highlights.length > 0) {
const highlighter = new HtmlHighlighter("mx_EventTile_searchHighlight", opts.highlightLink);
const safeHighlights = highlights.map(function(highlight) {
return sanitizeHtml(highlight, sanitizeParams);
});
const safeHighlights = highlights
// sanitizeHtml can hang if an unclosed HTML tag is thrown at it
// A search for `<foo` will make the browser crash
// an alternative would be to escape HTML special characters
// but that would bring no additional benefit as the highlighter
// does not work with those special chars
.filter((highlight: string): boolean => !highlight.includes("<"))
.map((highlight: string): string => sanitizeHtml(highlight, sanitizeParams));
germain-gg marked this conversation as resolved.
Show resolved Hide resolved
// XXX: hacky bodge to temporarily apply a textFilter to the sanitizeParams structure.
sanitizeParams.textFilter = function(safeText) {
return highlighter.applyHighlights(safeText, safeHighlights).join('');
Expand Down
3 changes: 2 additions & 1 deletion src/components/views/rooms/EventTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ interface IProps {
showReactions?: boolean;

// which layout to use
layout: Layout;
layout?: Layout;
germain-gg marked this conversation as resolved.
Show resolved Hide resolved

// whether or not to show flair at all
enableFlair?: boolean;
Expand Down Expand Up @@ -321,6 +321,7 @@ export default class EventTile extends React.Component<IProps, IState> {
static defaultProps = {
// no-op function because onHeightChanged is optional yet some sub-components assume its existence
onHeightChanged: function() {},
layout: Layout.Group,
};

static contextType = MatrixClientContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,28 @@ limitations under the License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import { haveTileForEvent } from "./EventTile";
import { SearchResult } from "matrix-js-sdk/src/models/search-result";
import EventTile, { haveTileForEvent } from "./EventTile";
import DateSeparator from '../messages/DateSeparator';
import SettingsStore from "../../../settings/SettingsStore";
import { UIFeature } from "../../../settings/UIFeature";
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
import { replaceableComponent } from "../../../utils/replaceableComponent";

@replaceableComponent("views.rooms.SearchResultTile")
export default class SearchResultTile extends React.Component {
static propTypes = {
// a matrix-js-sdk SearchResult containing the details of this result
searchResult: PropTypes.object.isRequired,

// a list of strings to be highlighted in the results
searchHighlights: PropTypes.array,

// href for the highlights in this result
resultLink: PropTypes.string,

onHeightChanged: PropTypes.func,
};
interface IProps {
// a matrix-js-sdk SearchResult containing the details of this result
searchResult: SearchResult;
// a list of strings to be highlighted in the results
searchHighlights?: string[];
// href for the highlights in this result
resultLink?: string;
onHeightChanged?: () => void;
permalinkCreator?: RoomPermalinkCreator;
}

render() {
const DateSeparator = sdk.getComponent('messages.DateSeparator');
const EventTile = sdk.getComponent('rooms.EventTile');
@replaceableComponent("views.rooms.SearchResultTile")
export default class SearchResultTile extends React.Component<IProps> {
public render() {
const result = this.props.searchResult;
const mxEv = result.context.getEvent();
const eventId = mxEv.getId();
Expand Down