Skip to content

socket: return EPROTONOSUPPORT on invalid protocol #16479

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 13, 2022
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
4 changes: 2 additions & 2 deletions src/library_sockfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ mergeInto(LibraryManager.library, {
createSocket: function(family, type, protocol) {
type &= ~{{{ cDefine('SOCK_CLOEXEC') | cDefine('SOCK_NONBLOCK') }}}; // Some applications may pass it; it makes no sense for a single process.
var streaming = type == {{{ cDefine('SOCK_STREAM') }}};
if (protocol) {
assert(streaming == (protocol == {{{ cDefine('IPPROTO_TCP') }}})); // if SOCK_STREAM, must be tcp
if (streaming && protocol && protocol != {{{ cDefine('IPPROTO_TCP') }}}) {
throw new FS.ErrnoError({{{ cDefine('EPROTONOSUPPORT') }}}); // if SOCK_STREAM, must be tcp or 0.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really ok to be 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my experience it is very common to use socket(AF_INET, SOCK_STREAM, 0) to create a IPv4 TCP socket. I have rarely seen IPPROTO_TCP. It works fine on Linux, FreeBSD, macOS, and Windows.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes. I see. From the man page:

Normally only  a  single  protocol exists to support a particular socket type within a given
protocol family, in which case protocol can be specified as 0.

}

// create our internal socket structure
Expand Down
38 changes: 38 additions & 0 deletions tests/sockets/test_create_socket.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2022 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/

#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
assert(sockfd >= 0);
close(sockfd);

sockfd = socket(AF_INET, SOCK_STREAM, 0);
assert(sockfd >= 0);
close(sockfd);

errno = 0;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_UDP);
assert(sockfd == -1);
assert(errno == EPROTONOSUPPORT);

errno = 0;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
assert(sockfd == -1);
assert(errno == EPROTONOSUPPORT);

puts("success");

return EXIT_SUCCESS;
}
3 changes: 3 additions & 0 deletions tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -8997,6 +8997,9 @@ def test_gethostbyname(self):
def test_getprotobyname(self):
self.do_runf(test_file('sockets/test_getprotobyname.c'), 'success')

def test_create_socket(self):
self.do_runf(test_file('sockets/test_create_socket.c'), 'success')

def test_socketpair(self):
self.do_run(r'''
#include <sys/socket.h>
Expand Down