diff --git a/main.go b/main.go index f5fb182..d5ca808 100644 --- a/main.go +++ b/main.go @@ -51,11 +51,12 @@ func setupRoutes(app *models.App) *http.ServeMux { router.Handle("/", m(controllers_pages.MainPageHandler(app))) // Обработка страницы со списком постов router.Handle("/posts/", m(controllers_pages.PostsPageHandler(app))) - // Обработка страничек постов - for key := range app.Posts { - postLink := string(key) - router.Handle(postLink, m(controllers_pages.PostPageHandler(app))) - } + } + + // Обработка страничек постов + for key := range app.Posts { + postLink := string(key) + router.Handle(postLink, m(controllers_pages.PostPageHandler(app))) } return router diff --git a/posts/test-code-blocks.md b/posts/test-code-blocks.md deleted file mode 100644 index 695548e..0000000 --- a/posts/test-code-blocks.md +++ /dev/null @@ -1,12 +0,0 @@ -# Тест блоков с кодом! - -Тестовый блок с кодом: - -``` -// Ответ на метод COUNT -#include -int main() { - printf("very long striiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiing!"); - return 0; -} -``` \ No newline at end of file diff --git a/posts/unsafe-change-string-go.md b/posts/unsafe-change-string-go.md index 5b7f396..c0d4e0b 100644 --- a/posts/unsafe-change-string-go.md +++ b/posts/unsafe-change-string-go.md @@ -7,6 +7,66 @@ Но в реальности все не так просто и при попытке что то положить по вычисленному адресу программа упадет с *segmentation fault (SIGSEGV)*. Чтобы этого избежать, предварительно надо выдать права на запись в страничку памяти где находится целевая строка. Сделать это можно через системные вызовы. -Код с пояснениями можно скачать [тут](https://git.hikan.ru/serr/unsafe-change-string-go) +``` +package main + +import ( + "fmt" + "syscall" + "unsafe" +) + +func main() { + s := "hello" + fmt.Println("Original:", s) + + // Строки в Go - структуры с двумя полями: указатель на данные и длина + // тут строка интерпретируется как структура + strHeader := (*struct { + data unsafe.Pointer + len int + })(unsafe.Pointer(&s)) + + // Вычисляем начало страницы памяти + pageSize := syscall.Getpagesize() + pageStart := uintptr(strHeader.data) - (uintptr(strHeader.data) % uintptr(pageSize)) + fmt.Printf( + "\nАдрес строки = %d\nразмер страницы памяти = %d\nадрес строки относительно начала страницы = %d\nадрес страницы = %d\n\n", + uintptr(strHeader.data), + uintptr(pageSize), + (uintptr(strHeader.data) % uintptr(pageSize)), + pageStart) + + // Имея адрес страницы и ее размер даю права на запись на данной странице памяти + ret, _, err := syscall.Syscall( + syscall.SYS_MPROTECT, + pageStart, + uintptr(pageSize), + uintptr(syscall.PROT_READ|syscall.PROT_WRITE), + ) + if ret != 0 { + panic("mprotect failed: " + err.Error()) + } + + // Теперь можно менять строку + // поменяю, например, пятый байт + fifthBytePtr := (*byte)(unsafe.Pointer(uintptr(strHeader.data) + 4)) + *fifthBytePtr = 0 + + // Восстанавливаю дефолтные права + ret, _, err = syscall.Syscall( + syscall.SYS_MPROTECT, + pageStart, + uintptr(pageSize), + uintptr(syscall.PROT_READ), + ) + if ret != 0 { + panic("mprotect restore failed: " + err.Error()) + } + + fmt.Println("Modified:", s) // Должно быть "hell" +} + +``` Тестил на **go version go1.22.2 linux/amd64** \ No newline at end of file