Skip to content
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

os:fix os.Errno 's nil pointer derefer in linux #828

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

luoliwoshang
Copy link
Contributor

@luoliwoshang luoliwoshang commented Oct 12, 2024

fix #825

The panic was in the use os.Errno.
in the generate ir in llgo like this demo.

; ModuleID = 'errno'
source_filename = "errno"

@errno = external global i32, align 4

declare i32 @putchar(i32)

define i32 @main() {
entry:
  %0 = load i32, ptr @errno, align 4
  %1 = add i32 %0, 48  ; Convert to ASCII digit (assuming errno is 0-9)
  call i32 @putchar(i32 %1)
  call i32 @putchar(i32 10)  ; Print newline
  ret i32 0
}

will cause follow error

/usr/bin/ld: errno: TLS definition in /lib/aarch64-linux-gnu/libc.so.6 section .tbss mismatches non-TLS reference in demo.o
/usr/bin/ld: /lib/aarch64-linux-gnu/libc.so.6: error adding symbols: bad value
clang: error: linker command failed with exit code 1 (use -v to see invocation)

we can see the marcos define the errno is actually call the__errno_location. in linux

extern int *__errno_location (void) __THROW __attribute_const__;
# define errno (*__errno_location ())

in macos is call __error

extern int * __error(void);
#define errno (*__error())

so we need another way to get the errno

; ModuleID = 'errno'
source_filename = "errno"

declare i32* @__errno_location()
declare i32 @putchar(i32)

define i32 @main() {
entry:
  %errno_ptr = call i32* @__errno_location()
  %errno_val = load i32, i32* %errno_ptr, align 4
  %ascii_val = add i32 %errno_val, 48  
  call i32 @putchar(i32 %ascii_val)
  call i32 @putchar(i32 10)  
  ret i32 0
}
root@be00d9b1c2c9:~/llgo/chore/_xtool/llcppsymg/oserrno/llvm# llvm-as demo.ll -o demo.bc
root@be00d9b1c2c9:~/llgo/chore/_xtool/llcppsymg/oserrno/llvm# llc -filetype=obj demo.bc -o demo.o
root@be00d9b1c2c9:~/llgo/chore/_xtool/llcppsymg/oserrno/llvm# clang demo.o -o demo
root@be00d9b1c2c9:~/llgo/chore/_xtool/llcppsymg/oserrno/llvm# ./demo
0

so,by wrapping the errno macro in a C function, we can obtain the actual errno value through a function call across different platforms.

 #include <errno.h>
 int llgoErrno() { return errno; }
//go:linkname Errno C.llgoErrno
func Errno() c.Int

result

we can get expected result of os.Errno's use

In this demo, when attempting to open a non-existent file, the program uses os.Error to retrieve the actual reason for the operation failure. This tests whether os.Error() is correctly referenced and functioning. The output showing "No such file or directory" confirms that the errno handling is working as expected across different platforms.

macos

❯ llgo run .
noexist: stat /var/folders/5j/sgtxqmbn1hbdqtgx5kkp6y700000gn/T/noexist.txt: No such file or directory
noexist: open /var/folders/5j/sgtxqmbn1hbdqtgx5kkp6y700000gn/T/noexist.txt: No such file or directory

linux

noexist: stat /tmp/noexist.txt: No such file or directory
noexist: open /tmp/noexist.txt: No such file or directory

Copy link

codecov bot commented Oct 12, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.47%. Comparing base (9ea88fe) to head (e9177c8).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #828   +/-   ##
=======================================
  Coverage   97.47%   97.47%           
=======================================
  Files          20       20           
  Lines        5157     5157           
=======================================
  Hits         5027     5027           
  Misses        110      110           
  Partials       20       20           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@xushiwei
Copy link
Member

please review @visualfc.
If os.Errno has bugs, it means os.Stdout/Stderr also has bugs.

@luoliwoshang
Copy link
Contributor Author

please review @visualfc. If os.Errno has bugs, it means os.Stdout/Stderr also has bugs.

os.Stdout/Stderr/Stdin works normally both in macos & linux

package main

import (
	"io"
	"fmt"
	"os"
)

func main() {
	fmt.Println("Message 1")
	fmt.Fprintln(os.Stdout, "Message 2")
	fmt.Fprintln(os.Stderr, "Message 3")

	input, err := io.ReadAll(os.Stdin)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error reading input: %v\n", err)
        return
    }
	fmt.Fprintf(os.Stdout, "You entered:\n%s", input)
}
root@be00d9b1c2c9:~/llgo/_demo/stdout# echo "Hello, World!" | llgo run demo.go
Message 1
Message 2
Message 3
You entered:
Hello, World!
root@be00d9b1c2c9:~/llgo/_demo/stdout# echo "Hello, World!" | go run demo.go
Message 1
Message 2
Message 3
You entered:
Hello, World!

@luoliwoshang
Copy link
Contributor Author

please review @visualfc. If os.Errno has bugs, it means os.Stdout/Stderr also has bugs.

/usr/include/stdio.h

/* Standard streams.  */
extern FILE *stdin;		/* Standard input stream.  */
extern FILE *stdout;		/* Standard output stream.  */
extern FILE *stderr;		/* Standard error output stream.  */
/* C89/C99 say they're macros.  Make them happy.  */
#define stdin stdin
#define stdout stdout
#define stderr stderr

c/os/_os/os.c Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unexpected nil pointer dereference when checking non-existent files existence on Linux and macOS
3 participants