fix crash when decoding malformed urls (#1865)

This commit is contained in:
Ajay Bura 2024-08-04 11:08:20 +05:30 committed by GitHub
parent 8ed78d48fb
commit 581211f13e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 20 additions and 8 deletions

View file

@ -25,6 +25,7 @@ import {
parseMatrixToUser, parseMatrixToUser,
testMatrixTo, testMatrixTo,
} from '../../plugins/matrix-to'; } from '../../plugins/matrix-to';
import { tryDecodeURIComponent } from '../../utils/dom';
const markNodeToType: Record<string, MarkType> = { const markNodeToType: Record<string, MarkType> = {
b: MarkType.Bold, b: MarkType.Bold,
@ -73,7 +74,7 @@ const elementToInlineNode = (node: Element): MentionElement | EmoticonElement |
return createEmoticonElement(src, alt || 'Unknown Emoji'); return createEmoticonElement(src, alt || 'Unknown Emoji');
} }
if (node.name === 'a') { if (node.name === 'a') {
const href = decodeURIComponent(node.attribs.href); const href = tryDecodeURIComponent(node.attribs.href);
if (typeof href !== 'string') return undefined; if (typeof href !== 'string') return undefined;
if (testMatrixTo(href)) { if (testMatrixTo(href)) {
const userMention = parseMatrixToUser(href); const userMention = parseMatrixToUser(href);

View file

@ -9,6 +9,7 @@ import {
useIntersectionObserver, useIntersectionObserver,
} from '../../hooks/useIntersectionObserver'; } from '../../hooks/useIntersectionObserver';
import * as css from './UrlPreviewCard.css'; import * as css from './UrlPreviewCard.css';
import { tryDecodeURIComponent } from '../../utils/dom';
const linkStyles = { color: color.Success.Main }; const linkStyles = { color: color.Success.Main };
@ -43,7 +44,7 @@ export const UrlPreviewCard = as<'div', { url: string; ts: number }>(
priority="300" priority="300"
> >
{typeof prev['og:site_name'] === 'string' && `${prev['og:site_name']} | `} {typeof prev['og:site_name'] === 'string' && `${prev['og:site_name']} | `}
{decodeURIComponent(url)} {tryDecodeURIComponent(url)}
</Text> </Text>
<Text truncate priority="400"> <Text truncate priority="400">
<b>{prev['og:title']}</b> <b>{prev['og:title']}</b>

View file

@ -29,6 +29,7 @@ import { AutoDiscoveryInfoProvider } from '../../hooks/useAutoDiscoveryInfo';
import { AuthFlowsLoader } from '../../components/AuthFlowsLoader'; import { AuthFlowsLoader } from '../../components/AuthFlowsLoader';
import { AuthFlowsProvider } from '../../hooks/useAuthFlows'; import { AuthFlowsProvider } from '../../hooks/useAuthFlows';
import { AuthServerProvider } from '../../hooks/useAuthServer'; import { AuthServerProvider } from '../../hooks/useAuthServer';
import { tryDecodeURIComponent } from '../../utils/dom';
const currentAuthPath = (pathname: string): string => { const currentAuthPath = (pathname: string): string => {
if (matchPath(LOGIN_PATH, pathname)) { if (matchPath(LOGIN_PATH, pathname)) {
@ -72,7 +73,7 @@ export function AuthLayout() {
const clientConfig = useClientConfig(); const clientConfig = useClientConfig();
const defaultServer = clientDefaultServer(clientConfig); const defaultServer = clientDefaultServer(clientConfig);
let server: string = urlEncodedServer ? decodeURIComponent(urlEncodedServer) : defaultServer; let server: string = urlEncodedServer ? tryDecodeURIComponent(urlEncodedServer) : defaultServer;
if (!clientAllowedServer(clientConfig, server)) { if (!clientAllowedServer(clientConfig, server)) {
server = defaultServer; server = defaultServer;
@ -94,7 +95,7 @@ export function AuthLayout() {
// if server is mismatches with path server, update path // if server is mismatches with path server, update path
useEffect(() => { useEffect(() => {
if (!urlEncodedServer || decodeURIComponent(urlEncodedServer) !== server) { if (!urlEncodedServer || tryDecodeURIComponent(urlEncodedServer) !== server) {
navigate( navigate(
generatePath(currentAuthPath(location.pathname), { generatePath(currentAuthPath(location.pathname), {
server: encodeURIComponent(server), server: encodeURIComponent(server),

View file

@ -26,6 +26,7 @@ import {
testMatrixTo, testMatrixTo,
} from './matrix-to'; } from './matrix-to';
import { onEnterOrSpace } from '../utils/keyboard'; import { onEnterOrSpace } from '../utils/keyboard';
import { tryDecodeURIComponent } from '../utils/dom';
const ReactPrism = lazy(() => import('./react-prism/ReactPrism')); const ReactPrism = lazy(() => import('./react-prism/ReactPrism'));
@ -134,8 +135,8 @@ export const factoryRenderLinkifyWithMention = (
attributes, attributes,
content, content,
}) => { }) => {
if (tagName === 'a' && testMatrixTo(decodeURIComponent(attributes.href))) { if (tagName === 'a' && testMatrixTo(tryDecodeURIComponent(attributes.href))) {
const mention = mentionRender(decodeURIComponent(attributes.href)); const mention = mentionRender(tryDecodeURIComponent(attributes.href));
if (mention) return mention; if (mention) return mention;
} }
@ -325,11 +326,11 @@ export const getReactCustomHtmlParser = (
} }
} }
if (name === 'a' && testMatrixTo(decodeURIComponent(props.href))) { if (name === 'a' && testMatrixTo(tryDecodeURIComponent(props.href))) {
const mention = renderMatrixMention( const mention = renderMatrixMention(
mx, mx,
roomId, roomId,
decodeURIComponent(props.href), tryDecodeURIComponent(props.href),
makeMentionCustomProps(params.handleMentionClick) makeMentionCustomProps(params.handleMentionClick)
); );
if (mention) return mention; if (mention) return mention;

View file

@ -196,3 +196,11 @@ export const setFavicon = (url: string): void => {
if (!favicon) return; if (!favicon) return;
favicon.setAttribute('href', url); favicon.setAttribute('href', url);
}; };
export const tryDecodeURIComponent = (encodedURIComponent: string): string => {
try {
return decodeURIComponent(encodedURIComponent);
} catch {
return encodedURIComponent;
}
};