Index: src/wp-admin/includes/image.php
===================================================================
--- src/wp-admin/includes/image.php	(revision 40124)
+++ src/wp-admin/includes/image.php	(working copy)
@@ -251,7 +251,15 @@
 			$editor = wp_get_image_editor( $file );
 
 			if ( ! is_wp_error( $editor ) ) { // No support for this type of file
-				$uploaded = $editor->save( $file, 'image/jpeg' );
+				/*
+				 * PDFs may have the same file filename as JPEGs.
+				 * Ensure the PDF preview image does not overwrite any JPEG images that already exist.
+				 */
+				$dirname = dirname( $file ) . '/';
+				$ext = '.' . pathinfo( $file, PATHINFO_EXTENSION );
+				$preview_file = $dirname . wp_unique_filename( $dirname, wp_basename( $file, $ext ) . '-pdf.jpg' );
+
+				$uploaded = $editor->save( $preview_file, 'image/jpeg' );
 				unset( $editor );
 
 				// Resize based on the full size image, rather than the source.
Index: tests/phpunit/tests/image/functions.php
===================================================================
--- tests/phpunit/tests/image/functions.php	(revision 40124)
+++ tests/phpunit/tests/image/functions.php	(working copy)
@@ -18,6 +18,13 @@
 		require_once( ABSPATH . WPINC . '/class-wp-image-editor-imagick.php' );
 
 		include_once( DIR_TESTDATA . '/../includes/mock-image-editor.php' );
+
+		// Ensure no legacy / failed tests detritus.
+		$folder = '/tmp/wordpress-gsoc-flyer*.{jpg,pdf}';
+
+		foreach ( glob( $folder, GLOB_BRACE ) as $file ) {
+			unlink( $file );
+		}
 	}
 
 	/**
@@ -373,25 +380,25 @@
 		$expected = array(
 			'sizes' => array(
 				'thumbnail' => array(
-					'file'      => "wordpress-gsoc-flyer-116x150.jpg",
+					'file'      => "wordpress-gsoc-flyer-pdf-116x150.jpg",
 					'width'     => 116,
 					'height'    => 150,
 					'mime-type' => "image/jpeg",
 				),
 				'medium'    => array(
-					'file'      => "wordpress-gsoc-flyer-232x300.jpg",
+					'file'      => "wordpress-gsoc-flyer-pdf-232x300.jpg",
 					'width'     => 232,
 					'height'    => 300,
 					'mime-type' => "image/jpeg",
 				),
 				'large'     => array(
-					'file'      => "wordpress-gsoc-flyer-791x1024.jpg",
+					'file'      => "wordpress-gsoc-flyer-pdf-791x1024.jpg",
 					'width'     => 791,
 					'height'    => 1024,
 					'mime-type' => "image/jpeg",
 				),
 				'full'      => array(
-					'file'      => "wordpress-gsoc-flyer.jpg",
+					'file'      => "wordpress-gsoc-flyer-pdf.jpg",
 					'width'     => 1088,
 					'height'    => 1408,
 					'mime-type' => "image/jpeg",
@@ -403,6 +410,9 @@
 		$this->assertSame( $expected, $metadata );
 
 		unlink( $test_file );
+		foreach ( $metadata['sizes'] as $size ) {
+			unlink ( '/tmp/' . $size['file'] );
+		}
 	}
 
 	/**
@@ -427,7 +437,7 @@
 		add_filter( 'fallback_intermediate_image_sizes', array( $this, 'filter_fallback_intermediate_image_sizes' ), 10, 2 );
 
 		$expected = array(
-			'file'      => 'wordpress-gsoc-flyer-77x100.jpg',
+			'file'      => 'wordpress-gsoc-flyer-pdf-77x100.jpg',
 			'width'     => 77,
 			'height'    => 100,
 			'mime-type' => 'image/jpeg',
@@ -441,6 +451,9 @@
 		remove_filter( 'fallback_intermediate_image_sizes', array( $this, 'filter_fallback_intermediate_image_sizes' ), 10 );
 
 		unlink( $test_file );
+		foreach ( $metadata['sizes'] as $size ) {
+			unlink ( '/tmp/' . $size['file'] );
+		}
 	}
 
 	function filter_fallback_intermediate_image_sizes( $fallback_sizes, $metadata ) {
@@ -449,4 +462,74 @@
 
 		return $fallback_sizes;
 	}
+
+	/**
+	 * Test PDF preview doesn't overwrite existing JPEG.
+	 * @ticket 39875
+	 */
+	public function test_pdf_preview_doesnt_overwrite_existing_jpeg() {
+		// Dummy JPEGs.
+		$jpg1_path = '/tmp/test.jpg'; // Straight.
+		file_put_contents( $jpg1_path, 'asdf' );
+		$jpg2_path = '/tmp/test-pdf.jpg'; // With PDF marker.
+		file_put_contents( $jpg2_path, 'fdsa' );
+
+		// PDF with same name as JPEG.
+		$pdf_path = '/tmp/test.pdf';
+		copy( DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf', $pdf_path );
+
+		$attachment_id = $this->factory->attachment->create_object( $pdf_path, 0, array(
+			'post_mime_type' => 'application/pdf',
+		) );
+
+		$this->assertNotEmpty( $attachment_id );
+
+		$metadata = wp_generate_attachment_metadata( $attachment_id, $pdf_path );
+
+		$this->assertTrue( is_array( $metadata ) );
+		$this->assertNotEmpty( $metadata['sizes']['full']['file'] );
+
+		$preview_path = '/tmp/' . $metadata['sizes']['full']['file'];
+
+		$this->assertTrue( is_file( $preview_path ) );
+		$this->assertNotEquals( $pdf_path, $preview_path );
+		$this->assertNotEquals( $jpg1_path, $preview_path );
+		$this->assertSame( 'asdf', file_get_contents( $jpg1_path ) );
+		$this->assertNotEquals( $jpg2_path, $preview_path );
+		$this->assertSame( 'fdsa', file_get_contents( $jpg2_path ) );
+
+		// Cleanup.
+		unlink( $jpg1_path );
+		unlink( $jpg2_path );
+		unlink( $pdf_path );
+		foreach ( $metadata['sizes'] as $size ) {
+			unlink ( '/tmp/' . $size['file'] );
+		}
+	}
+
+	/**
+	 * Test PDF preview low level renaming.
+	 * @ticket 39875
+	 */
+	public function test_pdf_preview_renaming() {
+		// Standard case.
+		$this->assertSame( '/tmp/test-pdf.jpg', self::pdf_preview_renaming( '/tmp/test.pdf' ) );
+
+		// Unlikely edge cases, but useful to document.
+
+		$this->assertSame( '/tmp/test-pdf.jpg', self::pdf_preview_renaming( '/tmp/test.' ) );
+
+		$this->assertSame( '/tmp/pdf-pdf.jpg', self::pdf_preview_renaming( '/tmp/.pdf' ) );
+
+		$this->assertSame( '/tmp/ext-pdf.jpg', self::pdf_preview_renaming( '/tmp/.ext' ) );
+
+		$this->assertSame( '/tmp/pdf.jpg', self::pdf_preview_renaming( '/tmp/.' ) );
+	}
+
+	protected static function pdf_preview_renaming( $file ) {
+		$dirname = dirname( $file ) . '/';
+		$ext = '.' . pathinfo( $file, PATHINFO_EXTENSION );
+		$preview_file = $dirname . wp_unique_filename( $dirname, wp_basename( $file, $ext ) . '-pdf.jpg' );
+		return $preview_file;
+	}
 }
