Skip to content

Commit 22258f7

Browse files
ivan-cxiequidoo
andcommitted
fix!: Use Viewtype::File for messages with invalid images, images of unknown size, images > 50 Mpx (#6825)
BREAKING CHANGE: messages with invalid images, images of unknown size, huge images, will have Viewtype::File After changing the logic of Viewtype selection, I had to fix 3 old tests that used invalid Base64 image data. Co-authored-by: iequidoo <117991069+iequidoo@users.noreply.github.com>
1 parent 5ab1078 commit 22258f7

File tree

5 files changed

+122
-34
lines changed

5 files changed

+122
-34
lines changed

src/constants.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ pub(crate) const WORSE_AVATAR_BYTES: usize = 20_000; // this also fits to Outloo
223223
pub const BALANCED_IMAGE_SIZE: u32 = 1280;
224224
pub const WORSE_IMAGE_SIZE: u32 = 640;
225225

226+
/// Limit for received images size. Bigger images become `Viewtype::File` to avoid excessive memory
227+
/// usage by UIs.
228+
pub const MAX_RCVD_IMAGE_PIXELS: u32 = 50_000_000;
229+
226230
// Key for the folder configuration version (see below).
227231
pub(crate) const DC_FOLDERS_CONFIGURED_KEY: &str = "folders_configured";
228232
// this value can be increased if the folder configuration is changed and must be redone on next program start

src/mimeparser.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,20 @@ impl MimeMessage {
13931393
} else {
13941394
Viewtype::File
13951395
}
1396+
} else if msg_type == Viewtype::Image
1397+
|| msg_type == Viewtype::Gif
1398+
|| msg_type == Viewtype::Sticker
1399+
{
1400+
match get_filemeta(decoded_data) {
1401+
// image size is known, not too big, keep msg_type:
1402+
Ok((width, height)) if width * height <= constants::MAX_RCVD_IMAGE_PIXELS => {
1403+
part.param.set_i64(Param::Width, width.into());
1404+
part.param.set_i64(Param::Height, height.into());
1405+
msg_type
1406+
}
1407+
// image is too big or size is unknown, display as file:
1408+
_ => Viewtype::File,
1409+
}
13961410
} else {
13971411
msg_type
13981412
};
@@ -1413,13 +1427,6 @@ impl MimeMessage {
14131427
};
14141428
info!(context, "added blobfile: {:?}", blob.as_name());
14151429

1416-
if mime_type.type_() == mime::IMAGE {
1417-
if let Ok((width, height)) = get_filemeta(decoded_data) {
1418-
part.param.set_int(Param::Width, width as i32);
1419-
part.param.set_int(Param::Height, height as i32);
1420-
}
1421-
}
1422-
14231430
part.typ = msg_type;
14241431
part.org_filename = Some(filename.to_string());
14251432
part.mimetype = Some(mime_type);

src/mimeparser/mimeparser_tests.rs

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -835,15 +835,7 @@ Content-Transfer-Encoding: base64
835835
Content-Disposition: inline;
836836
filename="JPEG_filename.jpg"
837837
838-
ISVb1L3m7z15Wy5w97a2cJg6W8P8YKOYfWn3PJ/UCSFcvCPtvBhcXieiN3M3ljguzG4XK7BnGgxG
839-
acAQdY8e0cWz1n+zKPNeNn4Iu3GXAXz4/IPksHk54inl1//0Lv8ggZjljfjnf0q1SPftYI7lpZWT
840-
/4aTCkimRrAIcwrQJPnZJRb7BPSC6kfn1QJHMv77mRMz2+4WbdfpyPQQ0CWLJsgVXtBsSMf2Awal
841-
n+zZzhGpXyCbWTEw1ccqZcK5KaiKNqWv51N4yVXw9dzJoCvxbYtCFGZZJdx7c+ObDotaF1/9KY4C
842-
xJjgK9/NgTXCZP1jYm0XIBnJsFSNg0pnMRETttTuGbOVi1/s/F1RGv5RNZsCUt21d9FhkWQQXsd2
843-
rOzDgTdag6BQCN3hSU9eKW/GhNBuMibRN9eS7Sm1y2qFU1HgGJBQfPPRPLKxXaNi++Zt0tnon2IU
844-
8pg5rP/IvStXYQNUQ9SiFdfAUkLU5b1j8ltnka8xl+oXsleSG44GPz6kM0RmwUrGkl4z/+NfHSsI
845-
K+TuvC7qOah0WLFhcsXWn2+dDV1bXuAeC769TkqkpHhdXfUHnVgK3Pv7u3rVPT5AMeFUGxRB2dP4
846-
CWt6wx7fiLp0qS9RrX75g6Gqw7nfCs6EcBERcIPt7DTe8VStJwf3LWqVwxl4gQl46yhfoqwEO+I=
838+
iVBORw0KGgoAAAANSUhEUgAAACAAAAAeCAAAAABoYUP1AAAAAXNSR0IArs4c6QAAAo1JREFUKJFdkdFuG0UUhr/szuxkxtlduzVx00jGUAhcI56CF0DiHXgFHqDiMfoCvAJC4gIJEBdVaZoGOY5dJ45r7zozmRlvzIVDm3Iu//PpP7/+s/OC/0+UREkEGZGr5N6mAX78MwISQEYJ6j6QYqZf7fzsYyRGJDISuQ9g6uMjW00WRCSRCP4DwNSEg496v828fC++B4yBGro7h+PliiiJHtR9B1vrmbtg359cOk+UqA8cDJm+eHu8yDfii6sAxK0u3hlsnPFn1WvT4XxYUqqtKu8cTMNKT8+nz3/aaWft3svKecBD/O9ETu2O//G7fXt5mHX2xwGP32aIEUNNvX/uh3z2pAkcKD+9XOLVNoMESw7YC+aPP8nqqSluyiuVaZRXCKLEQK3PxsP27UHe1lXV9eczCu2V8ippJA2gz+YTNTK9ttZOoYr+aeXwHp+k245cnFRNt1tmMJg3XV0dXQd3F5LcGn5fDnVQgwINRyFvtddnNmwBSW1qXfzNSDwoM+2A+aTbShfDd89Ka9ybiiLvGa33gK8THrWfVNUSSGLTALMRo/xBXnLbACu3QtRXY+sgkWnawKxCcLjPtr29gVZdPTidBUcSaXJeTfUL+mW4631Fmse+772xIGjSza/KTW/MYE/UCXPbEWs//Xxvqf8qZgYhG0jt8cnTnJpEgfDQ6rvE0n9tq66ICafil5OnOYt0hY94FUPoxI136uPpw4VIYNd+M5utrqvGpg0hc50bRl6BvLanX4pb/3347uWi/WgNHtYyyrdwszsX5fjZtwghy7C5sK2WgUoErcjIoEWr4fAHHhoRP+XZ86L/uMAarLFgsMBaAJhM8Ief9Ey7yHSmyXTp0GRoF7KQEdD/ArmtONKkgCleAAAAAElFTkSuQmCC
847839
848840
849841
----11019878869865180--
@@ -908,15 +900,7 @@ Content-ID: <part1.9DFA679B.52A88D69@example.org>
908900
Content-Disposition: inline;
909901
filename="1.png"
910902
911-
ISVb1L3m7z15Wy5w97a2cJg6W8P8YKOYfWn3PJ/UCSFcvCPtvBhcXieiN3M3ljguzG4XK7BnGgxG
912-
acAQdY8e0cWz1n+zKPNeNn4Iu3GXAXz4/IPksHk54inl1//0Lv8ggZjljfjnf0q1SPftYI7lpZWT
913-
/4aTCkimRrAIcwrQJPnZJRb7BPSC6kfn1QJHMv77mRMz2+4WbdfpyPQQ0CWLJsgVXtBsSMf2Awal
914-
n+zZzhGpXyCbWTEw1ccqZcK5KaiKNqWv51N4yVXw9dzJoCvxbYtCFGZZJdx7c+ObDotaF1/9KY4C
915-
xJjgK9/NgTXCZP1jYm0XIBnJsFSNg0pnMRETttTuGbOVi1/s/F1RGv5RNZsCUt21d9FhkWQQXsd2
916-
rOzDgTdag6BQCN3hSU9eKW/GhNBuMibRN9eS7Sm1y2qFU1HgGJBQfPPRPLKxXaNi++Zt0tnon2IU
917-
8pg5rP/IvStXYQNUQ9SiFdfAUkLU5b1j8ltnka8xl+oXsleSG44GPz6kM0RmwUrGkl4z/+NfHSsI
918-
K+TuvC7qOah0WLFhcsXWn2+dDV1bXuAeC769TkqkpHhdXfUHnVgK3Pv7u3rVPT5AMeFUGxRB2dP4
919-
CWt6wx7fiLp0qS9RrX75g6Gqw7nfCs6EcBERcIPt7DTe8VStJwf3LWqVwxl4gQl46yhfoqwEO+I=
903+
iVBORw0KGgoAAAANSUhEUgAAACAAAAAeCAAAAABoYUP1AAAAAXNSR0IArs4c6QAAAo1JREFUKJFdkdFuG0UUhr/szuxkxtlduzVx00jGUAhcI56CF0DiHXgFHqDiMfoCvAJC4gIJEBdVaZoGOY5dJ45r7zozmRlvzIVDm3Iu//PpP7/+s/OC/0+UREkEGZGr5N6mAX78MwISQEYJ6j6QYqZf7fzsYyRGJDISuQ9g6uMjW00WRCSRCP4DwNSEg496v828fC++B4yBGro7h+PliiiJHtR9B1vrmbtg359cOk+UqA8cDJm+eHu8yDfii6sAxK0u3hlsnPFn1WvT4XxYUqqtKu8cTMNKT8+nz3/aaWft3svKecBD/O9ETu2O//G7fXt5mHX2xwGP32aIEUNNvX/uh3z2pAkcKD+9XOLVNoMESw7YC+aPP8nqqSluyiuVaZRXCKLEQK3PxsP27UHe1lXV9eczCu2V8ippJA2gz+YTNTK9ttZOoYr+aeXwHp+k245cnFRNt1tmMJg3XV0dXQd3F5LcGn5fDnVQgwINRyFvtddnNmwBSW1qXfzNSDwoM+2A+aTbShfDd89Ka9ybiiLvGa33gK8THrWfVNUSSGLTALMRo/xBXnLbACu3QtRXY+sgkWnawKxCcLjPtr29gVZdPTidBUcSaXJeTfUL+mW4631Fmse+772xIGjSza/KTW/MYE/UCXPbEWs//Xxvqf8qZgYhG0jt8cnTnJpEgfDQ6rvE0n9tq66ICafil5OnOYt0hY94FUPoxI136uPpw4VIYNd+M5utrqvGpg0hc50bRl6BvLanX4pb/3347uWi/WgNHtYyyrdwszsX5fjZtwghy7C5sK2WgUoErcjIoEWr4fAHHhoRP+XZ86L/uMAarLFgsMBaAJhM8Ief9Ey7yHSmyXTp0GRoF7KQEdD/ArmtONKkgCleAAAAAElFTkSuQmCC
920904
--------------10CC6C2609EB38DA782C5CA9--
921905
922906
--------------779C1631600DF3DB8C02E53A--"#;
@@ -979,15 +963,7 @@ Content-Type: image/jpeg;
979963
Content-Transfer-Encoding: base64
980964
Content-ID: <image001.jpg@01D622B3.C9D8D750>
981965
982-
ISVb1L3m7z15Wy5w97a2cJg6W8P8YKOYfWn3PJ/UCSFcvCPtvBhcXieiN3M3ljguzG4XK7BnGgxG
983-
acAQdY8e0cWz1n+zKPNeNn4Iu3GXAXz4/IPksHk54inl1//0Lv8ggZjljfjnf0q1SPftYI7lpZWT
984-
/4aTCkimRrAIcwrQJPnZJRb7BPSC6kfn1QJHMv77mRMz2+4WbdfpyPQQ0CWLJsgVXtBsSMf2Awal
985-
n+zZzhGpXyCbWTEw1ccqZcK5KaiKNqWv51N4yVXw9dzJoCvxbYtCFGZZJdx7c+ObDotaF1/9KY4C
986-
xJjgK9/NgTXCZP1jYm0XIBnJsFSNg0pnMRETttTuGbOVi1/s/F1RGv5RNZsCUt21d9FhkWQQXsd2
987-
rOzDgTdag6BQCN3hSU9eKW/GhNBuMibRN9eS7Sm1y2qFU1HgGJBQfPPRPLKxXaNi++Zt0tnon2IU
988-
8pg5rP/IvStXYQNUQ9SiFdfAUkLU5b1j8ltnka8xl+oXsleSG44GPz6kM0RmwUrGkl4z/+NfHSsI
989-
K+TuvC7qOah0WLFhcsXWn2+dDV1bXuAeC769TkqkpHhdXfUHnVgK3Pv7u3rVPT5AMeFUGxRB2dP4
990-
CWt6wx7fiLp0qS9RrX75g6Gqw7nfCs6EcBERcIPt7DTe8VStJwf3LWqVwxl4gQl46yhfoqwEO+I=
966+
iVBORw0KGgoAAAANSUhEUgAAACAAAAAeCAAAAABoYUP1AAAAAXNSR0IArs4c6QAAAo1JREFUKJFdkdFuG0UUhr/szuxkxtlduzVx00jGUAhcI56CF0DiHXgFHqDiMfoCvAJC4gIJEBdVaZoGOY5dJ45r7zozmRlvzIVDm3Iu//PpP7/+s/OC/0+UREkEGZGr5N6mAX78MwISQEYJ6j6QYqZf7fzsYyRGJDISuQ9g6uMjW00WRCSRCP4DwNSEg496v828fC++B4yBGro7h+PliiiJHtR9B1vrmbtg359cOk+UqA8cDJm+eHu8yDfii6sAxK0u3hlsnPFn1WvT4XxYUqqtKu8cTMNKT8+nz3/aaWft3svKecBD/O9ETu2O//G7fXt5mHX2xwGP32aIEUNNvX/uh3z2pAkcKD+9XOLVNoMESw7YC+aPP8nqqSluyiuVaZRXCKLEQK3PxsP27UHe1lXV9eczCu2V8ippJA2gz+YTNTK9ttZOoYr+aeXwHp+k245cnFRNt1tmMJg3XV0dXQd3F5LcGn5fDnVQgwINRyFvtddnNmwBSW1qXfzNSDwoM+2A+aTbShfDd89Ka9ybiiLvGa33gK8THrWfVNUSSGLTALMRo/xBXnLbACu3QtRXY+sgkWnawKxCcLjPtr29gVZdPTidBUcSaXJeTfUL+mW4631Fmse+772xIGjSza/KTW/MYE/UCXPbEWs//Xxvqf8qZgYhG0jt8cnTnJpEgfDQ6rvE0n9tq66ICafil5OnOYt0hY94FUPoxI136uPpw4VIYNd+M5utrqvGpg0hc50bRl6BvLanX4pb/3347uWi/WgNHtYyyrdwszsX5fjZtwghy7C5sK2WgUoErcjIoEWr4fAHHhoRP+XZ86L/uMAarLFgsMBaAJhM8Ief9Ey7yHSmyXTp0GRoF7KQEdD/ArmtONKkgCleAAAAAElFTkSuQmCC
991967
992968
------=_NextPart_000_0003_01D622B3.CA753E60--
993969
"#;
@@ -2022,3 +1998,48 @@ async fn test_protected_date() -> Result<()> {
20221998
assert_eq!(alice_msg.get_timestamp(), bob_msg.get_timestamp());
20231999
Ok(())
20242000
}
2001+
2002+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
2003+
async fn test_huge_image_becomes_file() -> Result<()> {
2004+
let t = TestContext::new_alice().await;
2005+
let msg_id = receive_imf(
2006+
&t,
2007+
include_bytes!("../../test-data/message/image_huge_64M.eml"),
2008+
false,
2009+
)
2010+
.await?
2011+
.unwrap()
2012+
.msg_ids[0];
2013+
let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap();
2014+
// Huge image should be treated as file:
2015+
assert_eq!(msg.viewtype, Viewtype::File);
2016+
assert!(msg.get_file(&t).is_some());
2017+
assert_eq!(msg.get_filename().unwrap(), "huge_image.png");
2018+
assert_eq!(msg.get_filemime().unwrap(), "image/png");
2019+
// File has no width or height
2020+
assert!(msg.param.get_int(Param::Width).is_none());
2021+
assert!(msg.param.get_int(Param::Height).is_none());
2022+
Ok(())
2023+
}
2024+
2025+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
2026+
async fn test_4k_image_stays_image() -> Result<()> {
2027+
let t = TestContext::new_alice().await;
2028+
let msg_id = receive_imf(
2029+
&t,
2030+
include_bytes!("../../test-data/message/image_4k.eml"),
2031+
false,
2032+
)
2033+
.await?
2034+
.unwrap()
2035+
.msg_ids[0];
2036+
let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap();
2037+
// 4K image should be treated as image:
2038+
assert_eq!(msg.viewtype, Viewtype::Image);
2039+
assert!(msg.get_file(&t).is_some());
2040+
assert_eq!(msg.get_filename().unwrap(), "4k_image.png");
2041+
assert_eq!(msg.get_filemime().unwrap(), "image/png");
2042+
assert_eq!(msg.param.get_int(Param::Width).unwrap_or_default(), 3840);
2043+
assert_eq!(msg.param.get_int(Param::Height).unwrap_or_default(), 2160);
2044+
Ok(())
2045+
}

test-data/message/image_4k.eml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)
2+
From: Test Sender <sender@testrun.org>
3+
Subject: Large image test
4+
To: alice@example.org
5+
Message-ID: <big-image-test@testrun.org>
6+
Date: Thu, 17 Dec 2020 15:38:45 +0100
7+
User-Agent: Test-Agent/1.0
8+
MIME-Version: 1.0
9+
Content-Type: multipart/mixed;
10+
boundary="------------BIG_IMAGE_BOUNDARY"
11+
Content-Language: en-US
12+
13+
This is a multi-part message in MIME format.
14+
--------------BIG_IMAGE_BOUNDARY
15+
Content-Type: text/plain; charset=utf-8
16+
Content-Transfer-Encoding: 7bit
17+
18+
Here is a 4k image
19+
20+
--------------BIG_IMAGE_BOUNDARY
21+
Content-Type: image/png;
22+
name="4k_image.png"
23+
Content-Transfer-Encoding: base64
24+
Content-Disposition: attachment;
25+
filename="4k_image.png"
26+
27+
iVBORw0KGgoAAAANSUhEUgAADwAAAAhwCAIAAAAf3FwlAAAAEElEQVR4nAEFAPr/AP////8AAAAFCeiupAAAAABJRU5ErkJggg==
28+
--------------BIG_IMAGE_BOUNDARY--

test-data/message/image_huge_64M.eml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)
2+
From: Test Sender <sender@testrun.org>
3+
Subject: Large image test
4+
To: alice@example.org
5+
Message-ID: <huge-image-test@testrun.org>
6+
Date: Thu, 17 Dec 2020 15:38:45 +0100
7+
User-Agent: Test-Agent/1.0
8+
MIME-Version: 1.0
9+
Content-Type: multipart/mixed;
10+
boundary="------------HUGE_IMAGE_BOUNDARY"
11+
Content-Language: en-US
12+
13+
This is a multi-part message in MIME format.
14+
--------------HUGE_IMAGE_BOUNDARY
15+
Content-Type: text/plain; charset=utf-8
16+
Content-Transfer-Encoding: 7bit
17+
18+
Here is a huge image
19+
20+
--------------HUGE_IMAGE_BOUNDARY
21+
Content-Type: image/png;
22+
name="huge_image.png"
23+
Content-Transfer-Encoding: base64
24+
Content-Disposition: attachment;
25+
filename="huge_image.png"
26+
27+
iVBORw0KGgoAAAANSUhEUgAAH0AAAB9ACAIAAACJkzqjAAAAEElEQVR4nAEFAPr/AP////8AAAAFCeiupAAAAABJRU5ErkJggg==
28+
--------------HUGE_IMAGE_BOUNDARY--

0 commit comments

Comments
 (0)