That selfishness character in some open-source projects
Continuing with the topic of web servers and my work, as of the last days, of writing up some hands-on examples, I'm writing this post about a bug I found in Firefox. It's not new.
Before I do so, I do not want to pass the opportunity to touch on a topic that has been bugging me for quite some time now.
Let me start with a few examples.
I downloaded the source-code of Firefox -read below why. Nothing on the Mozilla project page alerts you of the size of the download required. It turns out that code is about 4GiB of download. But then you have to run some configuration scripts which also download some more stuff.
Don't ask me how much though: it's not mentioned nor notified anywhere!
That download forced me to update my Homebrew installation on my laptop. Yeah, I hadn't done so in quite a while. Hence, there where plenty of packages that were updated. Well, not always do you get warned about how much data it's gonna cost you nor will it ask you for confirmation to proceed.
While writing my previous post I decided to test the download of River, the Apache project originally developed by Sun under the name of Jini: Nowhere does it say how large is it gonna be such download...although this time a gzed-tarball ended up being somewhat less than 6MiB.
While browsing Bugzilla about the aforementioned bug, I came up way to often with a reply by what seemed Mozilla developers asking the posters commenting on buggy behaviour for a minimal example that would showcase the problem. It so is the case that what brought me to find out that same bug was precisely writing a minimal-case scenario for use with Firefox, namely, a basic server delivering some very simple HTML code back to the client.
So, developers of a huge project like Firefox, answering a question related to networking...and they cannot write themselves a minimal server in C that serves some 10 lines of HTML?
When I was doing Sys Admin work and would receive some request about an incident or something not working as they expected, I would always
- Quickly try to guess what might really be going on, then
- Come up with a minimal example showcasing what my guess was, and only then
- Ask the user for more clarification, if my little experiment wouldn't replicate the problem.
I find both types of examples unhelpful and selfish -for the lack of a better word right now. That's all I'm gonna say about that and open-source right now.
A 20 year old bug
And now about what I promised. Here is the bug:
Any web page whose HTML code starts like the following will trigger the bug in Firefox
<!doctype html><html><head><title>A 20yr-old bug</title><meta charset='utf-8'></head><body>...</body></html>
Mind you, a typical newspaper front page, e.g., the one from The Guardian below amounts to somewhat over 1MiB of data -there is not just text, but also pictures & ads.
So, If you went to visit your family in Malaysia and check out a newspaper with such an "stutter"-triggering HTML code, you'd be paying $\$$2 per page view if you use Firefox! Double as much as if you were using Safari, $\$1$. I think Chrome also works well -haven't checked yet-, hence only $\$$1 as well.
Why?
Because, not knowing better, those at Mozilla decided once that it was easier for the developers to force the browser requesting again the page every time the charset meta tag is not the first tag within the head tag!
So, this HTML code doesn't trigger the bug:
<!doctype html><html><head></head><meta charset='utf-8'><title>A 20yr-old bug</title><body>...</body></html>
Here the main bugzilla entries related to this tag. Notice how along these over 20 years the bug has been repeatedly rediscovered, fixed or simple disregarded!
- Bugzilla entry opened 20yrs ago updated 10 months ago. That is, it's still open -as of October 2020!
- Opened 17yrs ago, closed 8yrs ago...Status: Resolved!
How often does that happen?
A minimal setup to trigger the bug
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h> //memset
#include <unistd.h> //close
#include <stdio.h> //printf
#include <stdlib.h> //calloc
#define PORT "8080"
#define RDBUFLEN 1024
#define WRBUFLEN RDBUFLEN
int main(){
struct addrinfo hint;
memset(&hint,0,sizeof(hint) );
hint.ai_family = AF_INET6 ;
hint.ai_socktype = SOCK_STREAM ;
hint.ai_flags = AI_PASSIVE ; //for use w/ bind
//getaddrinfo
struct addrinfo *sadd ;
getaddrinfo(0, PORT, &hint, &sadd);
//socket
int server_s = socket(sadd->ai_family,
sadd->ai_socktype,
sadd->ai_protocol
);
//bind
bind(server_s, sadd->ai_addr, sadd->ai_addrlen);
//listen
listen(server_s,3);
//accept: blocking : waits for client to connect
struct sockaddr cadd;
socklen_t cadd_len = sizeof(cadd);
int client_s = 1;
int n=0;
while( (client_s=accept(server_s, &cadd, &cadd_len) )>0 ){
//recv
char* buf = (char*) calloc(RDBUFLEN,sizeof(char));
size_t rcvd = recv(client_s, buf, RDBUFLEN,0);
*(buf+rcvd)='\0';
printf("Received:\n%s\n",buf);
//send
char response[WRBUFLEN] =
"HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-type: text/html\r\n\r\n";
send(client_s,response,WRBUFLEN,0);
sprintf(response,
"<!doctype html>\r\n"
//"<html><head><meta charset='utf-8'><title>Lemon Inc.</title></head>\r\n" //Firefox sends 1 request only
//"<html><head><title>Lemon Inc.</title></head>\r\n" //Firefox sends 1 request only
"<html><head><title>Lemon Inc.</title><meta charset='utf-8'></head>\r\n" //Buggy Firefox sends 2 requests!
"<body style='background-color:#000000;color:#fff'>\r\n"
"<h1 style='font-size:48;color:#ffff33'>Lemon Inc.</h1>\r\n"
"<p>Your browser sent me following details:</p>\r\n"
"<div style='text-align:left;width:50%%;margin:auto;'>\r\n"
);
send(client_s,response,strlen(response),0);
int sent=send(client_s, buf , rcvd,0);
sprintf(response,"</div><br>Number of connections today: %d\r\n",++n);
send(client_s, response , strlen(response), 0);
sprintf(response , "</body></html>\r\n");
send(client_s, response , strlen(response), 0);
close(client_s);
}
//close
close(server_s);
printf("\n\nServer shutdown\n");
return 0;
}
No comments:
Post a Comment