As Steffen Ullrich said, it's not sufficient to consider a single application alone, but I'll write my answer assuming the user/application receiving the file trusts these uploads (which is bad if the file comes directly from an untrusted user).
On Windows, (I don't use Windows right now) the identification of file type, and thus what program(s) to read/run it with, is mostly done with file extensions. This means a
.pdf will be opened by a PDF reader by default, and should fail if the file is actually a
.exe file with a
.pdf extension. However, since the user, assuming they're not very computer-literate, may change some things to get it to work, such as renaming the file or changing what program to run the file with, all without understanding what problems that would cause. Additionally, there's the option to hide file extensions on Windows, meaning a file
not_a_virus.pdf.exe would be seen by the user as
not_a_virus.pdf while have a
.exe extension. Some programs may also check the file's MIME type like a Linux system would, which I'll discuss next.
On Linux systems (a lot of web servers are Linux), the file type is determined not (mainly) by file extensions, but by MIME types, using magic bytes. Binary files should have some magic bytes at the beginning of the file to identify the MIME type, as listed on Wikipedia. If a file has the bytes
47 49 46 38 37 61 at the beginning, running
file my_file should return
my_file: GIF image data, version 87a,, since those are the magic bytes of GIF files. Also, if a script (text) file has the line
#!/bin/bash on the first line, it will be identified as a "bash script", and running
./my_script will use the
bash binary to read/run the file.
As per best practice, you should validate both the file extensions & the file contents. Some programs use only the file extensions, some use only the contents (magic bytes), and some use both to identify the file type. You should simply assume the worst and not trust user inputs.