how can I read socket by blocking&none-multiplexing&sync mode? - c

I want to repeatedly request one specific url by maximum performance. I copied below source from github, but I think it isn't optimized for my case, so I have to tune it.
Which Option is best in my case?
block vs non-block
sync vs async
I think non-multiplexing is right, so I've to change select() function to the other one. Is this right?
char response[RESPONSE_SIZE + 1];
char *p = response, *q;
char *end = response + RESPONSE_SIZE;
char *body = 0;
enum {
length, chunked, connection
};
int encoding = 0;
int remaining = 0;
while (1) {
fd_set reads;
FD_ZERO(&reads);
FD_SET(server, &reads);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 200;
if (FD_ISSET(server, &reads)) {
int bytes_received = SSL_read(ssl, p, end - p);
p += bytes_received;
*p = 0;
if (!body && (body = strstr(response, "\r\n\r\n"))) {
*body = 0;
body += 4;
printf("Received Headers:\n%s\n", response);
q = strstr(response, "\nContent-Length: ");
if (q) {
encoding = length;
q = strchr(q, ' ');
q += 1;
remaining = strtol(q, 0, 10);
} else {
q = strstr(response, "\nTransfer-Encoding: chunked");
if (q) {
encoding = chunked;
remaining = 0;
} else {
encoding = connection;
}
}
printf("\nReceived Body:\n");
}
if (body) {
if (encoding == length) {
if (p - body >= remaining) {
printf("%.*s", remaining, body);
break;
}
} else if (encoding == chunked) {
do {
if (remaining == 0) {
if ((q = strstr(body, "\r\n"))) {
remaining = strtol(body, 0, 16);
if (!remaining) goto finish;
body = q + 2;
} else {
break;
}
}
if (p - body >= remaining) {
printf("%.*s", remaining, body);
body += remaining + 2;
remaining = 0;
}
} while (!remaining);
}
} //if (body)
} //if FDSET
} //end while(1)
finish:
buffer[0] = '\0';
printf("\nClosing socket...\n");

Related

Why am I getting this message in hackerrank "~ no response on stdout ~"? I don't know what I am missing>

Why am I getting this message in hackerrank "~ no response on stdout ~"? I don't know what I am missing?
I am bit frustrated right now because I have no clue about what to do.
So I was left with only choice to post this query on Stackoverflow.
Here is the link to the problem
Here is my complete code:
char* readline();
// Complete the countingValleys function below.
int countingValleys(int n, char* s)
{
int dwnhl = 0, level = 0;
bool frmsurface = true;
int k = strlen(s);
for (int i = 0; i < k; i++)
{
if (level == 0)
{
frmsurface = true;
}
if (s[i] == 'D')
{
level--;
if ((level < 0) && (frmsurface == true))
{
dwnhl++;
frmsurface = false;
//printf("went downhill %d ",i);
}
}
else if (s[i] == 'U')
{ //printf("went uphill %d ",i);
level++;
}
// printf("\nhello - %c",s[i]);
}
printf("\nNumber of downhill = %d \n", dwnhl);
return (dwnhl);
}
int main()
{
FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");
char* n_endptr;
char* n_str = readline();
int n = strtol(n_str, &n_endptr, 10);
if (n_endptr == n_str || *n_endptr != '\0')
{
exit(EXIT_FAILURE);
}
char* s = readline();
int result = countingValleys(n, s);
printf("%d\n", result);
return 0;
}
char* readline()
{
size_t alloc_length = 1024;
size_t data_length = 0;
char* data = malloc(alloc_length);
while (true)
{
char* cursor = data + data_length;
char* line = fgets(cursor, alloc_length - data_length, stdin);
if (!line)
{
break;
}
data_length += strlen(cursor);
if (data_length < alloc_length - 1 || data[data_length - 1] == '\n')
{
break;
}
size_t new_length = alloc_length << 1;
data = realloc(data, new_length);
if (!data)
{
break;
}
alloc_length = new_length;
}
if (data[data_length - 1] == '\n')
{
data[data_length - 1] = '\0';
}
data = realloc(data, data_length);
return data;
}
One problem is the way you handle frmsurface
The first time you enter the loop frmsurface is set to true. If the events are UUDD, your code will still count a "valley" because you don't clear frmsurface when you go up.
Instead of
if(level==0)
{
frmsurface=true;
}
you could try:
frmsurface = (level == 0);
but I don't really understand why you want the boolean. Just test for level == 0 instead. Something like:
if(s[i]=='D')
{
if(level==0)
{
dwnhl++;
}
level--;
}
else if (s[i]=='U')
{
level++;
}
Also I wonder if this line:
printf("\nNumber of downhill = %d \n", dwnhl);
must be removed.
Notice that
int k=strlen(s);
for(int i=0;i<k;i++)
could probably just be
for(int i=0;i<n;i++)
^
as n is passed to the function

STM32F103RB Nucleo transmit and receive usart

I have some problems with transmiting and receiving using usart. First informations that I want transmit are writen to circle buffer. Then indormations are send but some informations are lost.
Variables
enum {
BUF_SIZE = 100
};
char BUF_T[BUF_SIZE], BUF_R[BUF_SIZE];
uint8_t R_EMPTY = 0, R_BUSY = 0, T_EMPTY = 0, T_BUSY = 0;
Transmiting
void Send(void) {
uint8_t index = T_EMPTY;
for (int i = 0; i < 10; i++) {
BUF_T[index] = i+'0';
index++;
if (index >= BUF_SIZE) {
index = 0;
}
}
__disable_irq();
if (T_BUSY == T_EMPTY
&& __HAL_UART_GET_FLAG(&huart2,UART_FLAG_TXE) == SET) {
T_EMPTY = index;
T_BUSY++;
uint8_t tmp = BUF_T[T_BUSY];
if (T_BUSY >= BUF_SIZE) {
T_BUSY = 0;
}
HAL_UART_Transmit_IT(&huart2, (uint8_t*) &tmp, 1);
} else {
T_EMPTY = index;
}
__enable_irq();
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
//if (huart->Instance == USART2) {
if (T_BUSY != T_EMPTY) {
__disable_irq();
T_BUSY++;
uint8_t tmp = BUF_T[T_BUSY];
if (T_BUSY >= BUF_SIZE) {
T_BUSY = 0;
}
HAL_UART_Transmit_IT(&huart2, (uint8_t*) &tmp, 1);
__enable_irq();
}else {
Send();
}
//}
}
Screen from hterm
On picture can be seen that from time to time one char is lost. I don't understant why?
Regarding receiving can somebody tell mi if it OK?
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
//if (huart->Instance == USART2) {
uint8_t tmp = BUF_R[R_EMPTY];
R_EMPTY++;
if (R_EMPTY >= BUF_SIZE) {
R_EMPTY = 0;
}
HAL_UART_Receive_IT(&huart2, (uint8_t*) &tmp, 1);
//}
}

Circular Buffer Reader, I'm stuck

I am trying to implement a circular buffer, I'm writing to it just fine, all the received data is there, but something about my function to read from it doesn't work. No data gets saved into MtoHSdata.
The data I'm trying to read has a Start (>) and End (<) symbol, and is supposed to be sent via USART1.
Read data function:
void MtoHS(struct remoteM *Buff)
{
BYTE k = 0;
static BYTE st = 1;
switch (st)
{
case 1:
{
if ((*Buff).wr != (*Buff).re)
{
(*Buff).re = ((*Buff).re + 1) % (*Buff).max;
if ((*Buff).Buffer[(*Buff).re] == '>') // > == Start Symbol
{
k = 0;
MtoHSdata[k] = (*Buff).Buffer[(*Buff).re];
}
else if ((*Buff).Buffer[(*Buff).re] == '<') // < == End Symbol
{
MtoHSdata[k] = (*Buff).Buffer[(*Buff).re];
st = 5;
}
else
{
MtoHSdata[k] = (*Buff).Buffer[(*Buff).re]; // Data
k++;
}
}
}
break;
/* When End Symbol was read, send data to M */
case 5:
{
BYTE i = 0;
while (MtoHSdata[i] != '<')
{
USART_SendData(USART1, MtoHSdata[i]);
i++;
}
}
break;
default:
{
st = 1;
}
}
return;
}
Write data function (interrupt):
void USART1_IRQHandler(void)
{
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
{
uint16_t byteM = 0;
USART_GetITStatus(USART1, USART_IT_ORE);
byteM = USART_ReceiveData(USART1);
pRXD5->Buffer[pRXD5->wr] = byteM;
pRXD5->wr = (pRXD5->wr + 1) % pRXD5->max;
}
return;
}
I'm calling MtoHS function with the parameter 'pRXD5'.
Could anyone please tell me what I'm doing wrong?

eAthena - Adding 4 bytes to end of packet

I'm working on rewriting some source from eAthena. I need to add 4 bytes to the end of the packet. I'm trying to understand how. Wouldn't WFIFOL(sd->fd, len) = 0 add 4 bytes? Do I need to do a SWAP32 on this? Still learning thanks.
int clif_sendadditem(USER *sd, int num) {
char buf[128];
char buf2[128];
char *name = NULL;
char* owner = NULL;
int namelen;
int len;
int id;
//if(!sd->status.inventory[num].custom) {
id=sd->status.inventory[num].id;
//} else {
// id=sd->status.inventory[num].custom;
//}
if (id > 0 && !strcmpi(itemdb_name(id), "??")) {
memset(&sd->status.inventory[num], 0, sizeof(sd->status.inventory[num]));
return 0;
}
if (strlen(sd->status.inventory[num].real_name)) {
name = sd->status.inventory[num].real_name;
} else {
//if(!sd->status.inventory[num].custom) {
name = itemdb_name(id);
//} else {
// name = itemdb_namec(id);
//}
}
if (sd->status.inventory[num].amount > 1) {
sprintf(buf, "%s (%d)", name, sd->status.inventory[num].amount);
} else if(itemdb_type(sd->status.inventory[num].id)==ITM_SMOKE) {
//if(!sd->status.inventory[num].custom) {
sprintf(buf, "%s [%d %s]",name,sd->status.inventory[num].dura,itemdb_text(sd->status.inventory[num].id));
//} else {
// sprintf(buf, "%s [%d %s]",name,sd->status.inventory[num].dura,itemdb_textc(sd->status.inventory[num].custom));
//}
} else {
strcpy(buf, name);
}
namelen = strlen(buf);
if (!session[sd->fd])
{
session[sd->fd]->eof = 8;
return 0;
}
WFIFOHEAD(sd->fd, 255);
WFIFOB(sd->fd, 0) = 0xAA;
WFIFOB(sd->fd, 3) = 0x0F;
//WFIFOB(sd->fd, 4) = 0x03;
WFIFOB(sd->fd, 5) = num+1;
//if(!sd->status.inventory[num].custom) {
WFIFOW(sd->fd, 6) = SWAP16(itemdb_icon(id));
WFIFOB(sd->fd, 8) = itemdb_iconcolor(id);
//} else {
// WFIFOW(sd->fd, 6) = SWAP16(itemdb_iconc(id));
// WFIFOB(sd->fd, 8) = itemdb_iconcolorc(id);
//}
WFIFOB(sd->fd, 9) = namelen;
memcpy(WFIFOP(sd->fd, 10), buf, namelen);
len=namelen+1;
//if(!sd->status.inventory[num].custom) {
WFIFOB(sd->fd,len+9)=strlen(itemdb_name(id));
strcpy(WFIFOP(sd->fd,len+10),itemdb_name(id));
len+=strlen(itemdb_name(id))+1;
//} else {
// WFIFOB(sd->fd,len+9)=strlen(itemdb_namec(id));
// strcpy(WFIFOP(sd->fd,len+10),itemdb_namec(id));
// len+=strlen(itemdb_namec(id))+1;
//}
WFIFOL(sd->fd,len+9)=SWAP32(sd->status.inventory[num].amount);
len+=4;
if((itemdb_type(id)<3) || (itemdb_type(id)>17)) {
WFIFOB(sd->fd,len+9)=1;
WFIFOL(sd->fd,len+10)=0;
WFIFOB(sd->fd, len + 14) = 0;
len+=6;
} else {
WFIFOB(sd->fd,len+9)=0;
WFIFOL(sd->fd,len+10)=SWAP32(sd->status.inventory[num].dura);
WFIFOB(sd->fd, len + 14) = 0; //REPLACE WITH PROTECTED
len+=6;
}
if(sd->status.inventory[num].owner_id) {
owner=map_id2name(sd->status.inventory[num].owner_id);
WFIFOB(sd->fd,len+9)=strlen(owner);
strcpy(WFIFOP(sd->fd,len+10),owner);
len+=strlen(owner)+1;
FREE(owner);
} else {
WFIFOB(sd->fd,len+9)=0; //len of owner
len+=1;
}
//WFIFOW(sd->fd, len + 9) = SWAP16(0);
WFIFOW(sd->fd, 1) = SWAP16(len + 6);
WFIFOSET(sd->fd, encrypt(sd->fd));
return 0;
}
I was miscounting and changed the commented
//WFIFOW(sd->fd, len + 9) = SWAP16(0);
to
WFIFOL(sd->fd, len + 9) = SWAP32(0);
and then changed to len+10 at end

Fix Buffer Overflow Exploit on Web Server

I have a buffer overflow vulnerability in a simple webserver. It can be exploited with a http GET request. I'm having trouble figuring out how to fix it. My guess is that it has to do with: char hdrval[1024]; but I could be wrong. Can anyone else see whats wrong?
Code:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#define _XOPEN_SOURCE
typedef struct {
char *method;
char *uri;
char *version;
char *headers;
} httpreq_t;
/* NOTE: this function is based on a function provided in the GNU "timegm" man
page. timegm is a GNU extension to time.h that returns the given tm struct as
a UNIX timestamp in GMT/UTC, rather than local time. The man page suggests a
function similar to the one below as a portable equivalent.
*/
time_t my_timegm(struct tm *tm) {
time_t ret;
char *tz;
tz = getenv("TZ");
putenv("TZ=GMT");
tzset();
ret = mktime(tm);
if (tz) {
char envstr[strlen(tz) + 4];
envstr[0] = '\0';
strcat(envstr, "TZ=");
strcat(envstr, tz);
putenv(envstr);
} else {
putenv("TZ=");
}
tzset();
return ret;
}
char *get_header(const httpreq_t *req, const char* headername) {
char *hdrptr;
char *hdrend;
char *retval = NULL;
char searchstr[strlen(headername) + 5];
strcpy(searchstr, "\r\n");
strcat(searchstr, headername);
strcat(searchstr, ": ");
if (hdrptr = strstr(req->headers, searchstr)) {
hdrptr += strlen(searchstr);
if (hdrend = strstr(hdrptr, "\r\n")) {
char hdrval[1024]; // temporary return value
memcpy((char *)hdrval, hdrptr, (hdrend - hdrptr));
hdrval[hdrend - hdrptr] = '\0'; // tack null onto end of header value
int hdrvallen = strlen(hdrval);
retval = (char *)malloc((hdrvallen + 1) * sizeof(char)); // malloc a space for retval
strcpy(retval, (char *)hdrval);
} else {
retval = (char *)malloc((strlen(hdrptr) + 1) * sizeof(char)); //
strcpy(retval, hdrptr);
}
}
return retval;
}
/* As long as str begins with a proper HTTP-Version followed by delim, returns a
pointer to the start of the version number (e.g., 1.0). Returns NULL otherwise.
*/
char *http_version_str(char *str, char *delim) {
char *vstart = strstr(str, "HTTP/");
char *vnumstart = str + 5;
char *vdot = strchr(str, '.');
char *vend = strstr(str, delim);
char *digits = "0123456789";
int majvlen = 0;
int minvlen = 0;
if (!vstart || !vdot // something's missing
|| vstart != str) // str doesn't start with "HTTP/"
return NULL;
majvlen = strspn(vnumstart, digits);
minvlen = strspn(vdot + 1, digits);
if (majvlen < 1 || (vnumstart + majvlen) != vdot // bad major version
|| minvlen < 1 || (vdot + minvlen + 1) != vend) // bad minor version
return NULL;
return vnumstart;
}
/* Fills req with the request data from datastr. Returns 0 on success.
*/
int parsereq(httpreq_t *req, char *datastr) {
char *position;
char *last_position = datastr;
char *temp_position;
int matchlen;
req->method = "";
req->uri = "";
req->version = "";
req->headers = "";
if (!(position = strchr(last_position, ' '))) {
return 1;
}
matchlen = (int)(position - last_position);
req->method = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->method, last_position, matchlen);
req->method[matchlen] = '\0';
last_position = position + 1;
if (!(position = strchr(last_position, ' '))
&& !(position = strstr(last_position, "\r\n"))) {
return 1;
}
// strip any query string out of the URI
if ((temp_position = strchr(last_position, '?')) && temp_position < position)
matchlen = (int)(temp_position - last_position);
else
matchlen = (int)(position - last_position);
req->uri = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->uri, last_position, matchlen);
req->uri[matchlen] = '\0';
if (position[0] == '\r') {
req->version = "0.9";
req->headers = "";
return 0; // simple req -- uri only
}
// If we get here, it's a full request, get the HTTP version and headers
last_position = position + 1;
if (!(position = strstr(last_position, "\r\n"))
|| !(last_position = http_version_str(last_position, "\r\n"))) {
return 1;
}
matchlen = (int)(position - last_position);
req->version = (char *)malloc((matchlen + 1) * sizeof(char));
memcpy(req->version, last_position, matchlen);
req->version[matchlen] = '\0';
last_position = position;
req->headers = (char *)malloc(strlen(last_position) * sizeof(char));
strcpy(req->headers, last_position);
return 0;
}
char *contype(char *ext) {
if (strcmp(ext, "html") == 0) return "text/html";
else if (strcmp(ext, "htm") == 0) return "text/html";
else if (strcmp(ext, "jpeg") == 0) return "image/jpeg";
else if (strcmp(ext, "jpg") == 0) return "image/jpeg";
else if (strcmp(ext, "gif") == 0) return "image/gif";
else if (strcmp(ext, "txt") == 0) return "text/plain";
else return "application/octet-stream";
}
char *status(int statcode) {
if (statcode == 200) return "200 OK";
else if (statcode == 304) return "304 Not Modified";
else if (statcode == 400) return "400 Bad Request";
else if (statcode == 403) return "403 Forbidden";
else if (statcode == 404) return "404 Not Found";
else if (statcode == 500) return "500 Internal Server Error";
else if (statcode == 501) return "501 Not Implemented";
else return "";
}
int send_response(int sockfd, httpreq_t *req, int statcode) {
int urifd;
const int BUFSIZE = 1024;
char sendmessage[BUFSIZE];
char *path = req->uri;
if (req->uri == NULL || req->method == NULL ||
req->headers == NULL || req->version == NULL) {
return 0;
}
if ((path[0] == '/') || ((strstr(path, "http://") == path)
&& (path = strchr(path + 7, '/')))) {
path += 1; // remove leading slash
if (path[0] == '\0') { // substituting in index.html for a blank URL!
path = "index.html";
} else if (path[strlen(path) - 1] == '/') {
//concatenating index.html for a /-terminated URL!
strcat(path, "index.html");
}
} else {
statcode = 400;
}
if (statcode == 200 && (urifd = open(path, O_RDONLY, 0)) < 0) {
if (errno == ENOENT || errno == ENOTDIR) { // file or directory doesn't exist
statcode = 404;
} else if (errno == EACCES) { // access denied
statcode = 403;
} else {
// some other file access problem
statcode = 500;
}
}
if (strstr(path, "..") != NULL) {
statcode = 500;
}
sendmessage[0] = '\0';
if (strcmp(req->version, "0.9") != 0) { // full request
char *ext; // file extension
time_t curtime;
char *imstime;
struct tm tm;
struct stat stbuf;
if (statcode == 200) {
if (ext = strrchr(path, '.')) ext++; // skip the '.'
else ext = "";
} else {
// errors are always html messages
ext = "html";
}
// Conditional GET
if ((strcmp(req->method, "GET") == 0)
&& (statcode == 200)
&& (imstime = get_header(req, "If-Modified-Since"))) {
// Get statistics about the requested URI from the local filesystem
if (stat(path, &stbuf) == -1) {
statcode = 500;
}
if (!strptime(imstime, "%a, %d %b %Y %H:%M:%S GMT", &tm)
&& !strptime(imstime, "%a, %d-%b-%y %H:%M:%S GMT", &tm)
&& !strptime(imstime, "%a %b %d %H:%M:%S %Y", &tm)) {
// badly formatted date
statcode = 400;
}
if (stbuf.st_mtime <= my_timegm(&tm)) {
// Not Modified
statcode = 304;
}
}
time(&curtime); // time for Date: header
strcat(sendmessage, "HTTP/1.0 ");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "\r\nDate: ");
strncat(sendmessage, asctime(gmtime(&curtime)), 24);
strcat(sendmessage, "\r\nServer: Frobozz Magic Software Company Webserver v.002");
strcat(sendmessage, "\r\nConnection: close");
strcat(sendmessage, "\r\nContent-Type: ");
strcat(sendmessage, contype(ext));
strcat(sendmessage, "\r\n\r\n");
}
if (statcode != 200) {
strcat(sendmessage, "<html><head><title>");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "</title></head><body><h2>HTTP/1.0</h2><h1>");
strcat(sendmessage, status(statcode));
strcat(sendmessage, "</h1><h2>URI: ");
strcat(sendmessage, path);
strcat(sendmessage, "</h2></body></html>");
}
if (sendmessage[0] != '\0') {
// send headers as long as there are headers to send
if (send(sockfd, sendmessage, strlen(sendmessage), 0) < 0) {
perror("send");
pthread_exit(NULL);
}
}
if (statcode == 200 && (strcmp(req->method, "HEAD") != 0)) {
// send the requested file as long as there's no error and the
// request wasn't just for the headers
int readbytes;
while (readbytes = read(urifd, sendmessage, BUFSIZE)) {
if (readbytes < 0) {
perror("read");
pthread_exit(NULL);
}
if (send(sockfd, sendmessage, readbytes, 0) < 0) {
perror("send");
pthread_exit(NULL);
}
}
}
}
void *data_thread(void *sockfd_ptr) {
int sockfd = *(int *) sockfd_ptr;
const int BUFSIZE = 5;
char recvmessage[BUFSIZE];
char *headerstr = NULL;
char *newheaderstr = NULL;
int recvbytes = 0;
int curheadlen = 0;
int totalheadlen = 0;
httpreq_t req;
int statcode = 200;
int done = 0;
int seen_header = 0;
char *header_end;
int content_length = 0;
char *qstr;
free(sockfd_ptr); // we have the int value out of this now
recvmessage[BUFSIZE - 1] = '\0'; // mark end of "string"
/* Read incoming client message from the socket */
while(!done && (recvbytes = recv(sockfd, recvmessage, BUFSIZE - 1, 0))) {
if (recvbytes < 0) {
perror("recv");
pthread_exit(NULL);
}
recvmessage[recvbytes] = '\0';
if (seen_header) {
// getting the entity body
content_length -= recvbytes;
if (content_length <= 0) done = 1;
} else {
newheaderstr = (char *) malloc((totalheadlen + recvbytes + 1) * sizeof(char));
newheaderstr[totalheadlen + recvbytes] = '\0';
memcpy(newheaderstr, headerstr, totalheadlen);
memcpy(newheaderstr + totalheadlen, recvmessage, recvbytes);
if (headerstr) free(headerstr);
headerstr = newheaderstr;
totalheadlen += recvbytes;
header_end = strstr(headerstr, "\r\n\r\n");
if (header_end) {
seen_header = 1;
header_end[2] = '\0';
if (parsereq(&req, headerstr) != 0) {
statcode = 400;
}
if (strcmp(req.method, "POST") == 0) {
// grab the body length
char *clenstr = get_header(&req, "Content-Length");
if (clenstr) {
content_length = atoi(clenstr) - ((headerstr + totalheadlen) - header_end - 4);
if (content_length <= 0) done = 1;
free(clenstr);
} else {
statcode = 400; // bad request -- no content length
done = 1;
}
} else {
// This isn't a POST, so there's no entity body
done = 1;
if (strcmp(req.method, "GET") != 0
&& strcmp(req.method, "HEAD") != 0) {
statcode = 501; // unknown request method
}
}
}
}
} // end of recv while loop
// used to deref a NULL pointer here... :(
if (headerstr != NULL) {
printf("%s\n", headerstr);
free(headerstr);
}
send_response(sockfd, &req, statcode);
close(sockfd);
return NULL;
}
int main(int argc, char *argv[]) {
int acc, sockfd, clen, port;
struct hostent *he;
struct sockaddr_in caddr, saddr;
if(argc <= 1) {
fprintf(stderr, "No port specified. Exiting!\n");
exit(1);
}
port = atoi(argv[1]);
/* Obtain name and address for the local host */
if((he=gethostbyname("localhost"))==NULL) {
herror("gethostbyname");
exit(1);
}
/* Open a TCP (Internet Stream) socket */
if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1) {
perror("socket");
exit(1);
}
/* Create socket address structure for the local host */
memset((char *) &saddr, '\0', sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(port);
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
/* Bind our local address so that the client can send to us */
if(bind(sockfd,(struct sockaddr *) &saddr,sizeof(saddr)) == -1) {
perror("bind");
exit(1);
}
if(listen(sockfd,5) < 0) {
perror("listen");
exit(1);
}
/* Infinite loop for receiving and processing client requests */
for(;;) {
clen=sizeof(caddr);
/* Wait for a connection for a client process */
acc=accept(sockfd,(struct sockaddr *) &caddr,(socklen_t*)&clen);
if(acc < 0) {
perror("accept");
exit(1);
} else {
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t));
int *sockfd_ptr = (int *) malloc(sizeof(int));
*sockfd_ptr = acc;
pthread_create(thread, NULL, data_thread, sockfd_ptr);
}
}
return 0;
}
I guess you could have a bound check before copying to the buffer?
For example, add
if(hdrend - hdrptr >= 1024)
exit(1)
before
memcpy((char *)hdrval, hdrptr, (hdrend - hdrptr));
The segfault happens at the point below.
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7ff4b70 (LWP 3902)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7ff4b70 (LWP 3902)]
0x08049507 in send_response (sockfd=6, req=0xb7ff4340, statcode=200)
at server/webserver.c:219
warning: Source file is more recent than executable.
219 if (req->uri == NULL || req->method == NULL ||
The memory address is
(gdb) p $_siginfo._sifields._sigfault.si_addr
$3 = (void *) 0x69cb120
The code that needs to be rewritten is
214 int urifd;
215 const int BUFSIZE = 1024;
216 char sendmessage[BUFSIZE];
217 char *path = req->uri;
218
219 if (req->uri == NULL || req->method == NULL ||
220 req->headers == NULL || req->version == NULL) {
221 return 0;

Resources