* scanf에서 % n 연산자의 일관성 및 동작

i336_

저는 현재 nginx 인스턴스 뒤에있는 C 프로그램 (Linux에서 glibc를 사용하여 컴파일 됨)에 약간의 HTTP 처리를 구축하고 있으며이 sscanf시나리오에서 인수 토큰 화를 안전하게 연기해야한다고 생각했습니다 .

URI에서 쿼리를 추출하는 것이 간단하다는 것을 알게되어 매우 기뻤습니다.

char *path = "/events?a=1&b=2&c=3";

char query[64] = {0};

sscanf(path, "%*[^?]?%64s HTTP", query); // query = "a=1&b=2&c=3"

하지만 얼마나 빨리 i͏̠͚̣̗̲n͓̭̞̹t͈e҉̝̟̘̺r͈e̫st̩̟̠i͏͈͇n͏̠͍g̞͝   :(

int pos = -1;
char arg[32] = {0}, value[32] = {0};

int c = sscanf(query, "%32[^=]=%32[^&]&%n", &arg, &value, &pos);

의 입력을 위해 a=1&b=2내가 할, arg="a", value="1", c=2, pos=4. 완벽 함 : 이제 sscanf를 다시 실행 path + pos하여 다음 인수를 얻을 수 있습니다. 내가 왜 여기에 있습니까?

음, 동안 a=1&동일하게 위의 동작합니다가, a=1생산 arg="a", value="1", c=2, pos=-1 . 이걸 어떻게 만드나요?

문서를 샅샅이 뒤져서 읽었습니다.

       n      Nothing  is expected; instead, the number of characters consumed
              thus far from the input is  stored  through  the  next  pointer,
              which  must  be  a pointer to int.  This is not a conversion and
              does not increase the count returned by the function.   The  as‐
              signment  can  be  suppressed  with the * assignment-suppression
              character, but the effect on  the  return  value  is  undefined.
              Therefore %*n conversions should not be used.

단락의 50 % 이상이 부기 세부 사항을 언급합니다. 내가보고있는 행동은 논의되지 않았습니다.

Google 검색 결과를 돌아 다니며 Wikipedia의 Scanf_format_string 항목 (최고 인기 항목)에 빠르게 도달 했지만, 어 ...

2020 년 6 월 현재 형식 사양이 비어 있습니다. 좋아요 ... 아무도 보지 못하는 기능을 사용하여 여기 회전 초에있는 것 같습니다. 그것은 나의 남은 자신감을 불러 일으키지 않습니다.

것으로 보인다 무엇인지 살펴받는 %n같은 scanf-internal.c에서 구현을 , 나는 관련 논의에 대한 표준 불일치를 코드 (선)의 60 %를 발견, 구성하는 (39.6 % 구현의 사소한이며, 0.4 %는 실제 코드 전체 " done++;").

그것은 * 이 나타납니다는 그의 glibc의 동작은 내부 값 떠날 것입니다 * done(내가 사용하여 액세스 %n정의되지 않았거나 오히려, - - 일부 동작을 변경합니다 그것을하지 않는 한) 그대로를. %n이런 식으로 사용 하는 것은 예상치 못한 일이고 내가 완전히 "용이 여기 있습니다"영역에있는 것 같습니까? :(

나는 내가 사용할 것 같지 않다 scanf...

완전성을 위해 여기에 제가보고있는 내용을 요약 한 것이 있습니다.

#include <stdio.h>

void test(const char *str) {
  int pos = -1;
  char arg[32] = {0}, value[32] = {0};
  int c = sscanf(str, "%32[^=]=%32[^&]&%n", (char *)&arg, (char *)&value, &pos);
  printf("\"%s\": c=%d arg=\"%s\" value=\"%s\" pos=%d\n", str, c, arg, value, pos);
}

int main() {
  test("a=1&b=2"); // "a=1&b=2": c=2 arg="a" value="1" pos=4
  test("a=1&");    // "a=1&": c=2 arg="a" value="1" pos=4
  test("a=1");     // "a=1": c=2 arg="a" value="1" pos=-1
}
네이트 엘 드리지

나는 C 표준 pos이 귀하의 예에서 의 값 이 변하지 않음을 보장한다고 생각합니다 .

C17 7.21.6.2는 다음과 같이 설명합니다 fscanf.

(4) fscanf 함수는 형식의 각 지시문을 차례로 실행합니다. 모든 지시문이 실행되었거나 지시문이 실패하면 (아래 설명 참조) 함수가 반환됩니다. 실패는 입력 실패 (인코딩 오류 발생 또는 입력 문자를 사용할 수 없음) 또는 일치 실패 (부적절한 입력으로 인한)로 설명됩니다.

[...]

(6) 일반 멀티 바이트 문자 인 지시문은 스트림의 다음 문자를 읽어 실행됩니다. 이러한 문자 중 하나가 지시문을 구성하는 문자와 다른 경우 지시문은 실패하고 다른 문자와 후속 문자는 읽지 않은 상태로 유지됩니다. 마찬가지로 파일 끝, 인코딩 오류 또는 읽기 오류로 인해 문자를 읽을 수없는 경우 지시문이 실패합니다.

(여기서 "멀티 바이트 문자"에는 &.) 와 같은 일반 1 바이트 문자가 포함됩니다 .

따라서 귀하의 "a=1"예에서 지시문 %32[^=], =%32[^&]모두 성공하고 이제 문자열의 끝에 도달했습니다. 7.21.6.7 sscanf에서 "문자열의 끝에 도달하는 것은 fscanf 함수에 대한 파일의 끝을 만나는 것과 같습니다."라고 설명되어 있습니다. 따라서 문자를 읽을 수 없으므로 &지시문이 실패 sscanf하고 더 이상 수행하지 않고 반환됩니다. %n지시어는 실행되지, 아무것도 그래서 그 값을 수정할 수있는 권한을 지닌 일이 결코 pos. 따라서 이전과 동일한 값, 즉 -1을 가져야합니다.

저는이 사건이 예상치 못한 일이라고 생각하지 않습니다. 이미 기존 규칙에 적용되어 있으므로 누구도 명시 적으로 언급하지 않았습니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

ANTLRv4 문법에서 Java 연산자의 연관성 및 우선 순위

분류에서Dev

JavaScript의 논리 연산자 및 동작

분류에서Dev

이해 '| '및'& '연산자 동작 (R의 논리 연산자)

분류에서Dev

파이썬의 ** 연산자 및 * 연산자를 사용하는 동안 서명

분류에서Dev

값 내부의 특수 문자는 SQL Server의 = 연산자와 동일하게 작동하는 동안 like 연산자에서 작동하지 않습니다.

분류에서Dev

복사 생성자 및 assignemnt 연산자 오버로드가 C ++에서 작동하지 않음

분류에서Dev

동일한 테이블에서 N : N 및 1 : N 관계를 생성하는 방법은 무엇입니까?

분류에서Dev

&& 및 ||를 사용할 수 있습니까? Java의 동일한 if 문에서 연산자?

분류에서Dev

Hive에서 여러 개의 동일한 연산자 및 함수 호출을 최적화 하시겠습니까?

분류에서Dev

c 프로그래밍에서 논리 및 (&&) 및 논리 또는 (||) 연산자의 혼란스러운 동작

분류에서Dev

## 일명 토큰 붙여 넣기 연산자가 C 및 C ++의 주석에 대해 작동하지 않는 이유는 무엇입니까?

분류에서Dev

배열에서 "보다 큼"(및 다른 부등식 비교 연산자)의 동작

분류에서Dev

동일한 모델에 대한 Rails 다형성 연관 및 has_many

분류에서Dev

생성자 이동 및 할당 이동. 기본 클래스의 연산자

분류에서Dev

">"및 "<"연산자는 문자열 비교에서 어떻게 작동합니까?

분류에서Dev

부동 소수점에 관한 연산의 연관성

분류에서Dev

C #의 연산자 우선 순위 및 연관성

분류에서Dev

생성자 이동 및 클래스에 대한 할당 연산자 이동

분류에서Dev

$ set 및 위치 연산자가 Java에서 작동하지 않습니까?

분류에서Dev

PHP에서 삼항 및 비교 연산자는 어떻게 작동합니까?

분류에서Dev

관계 연산자 요소를 사용하여 numpy 배열의 여러 인덱스에서 작동

분류에서Dev

printf-C 언어에서 사용될 때 관계 연산자의 출력 동작

분류에서Dev

PHP 임의 연산자 및 작업

분류에서Dev

&& 및 ||의 혼동 사용 연산자

분류에서Dev

접미사 및 접두사 연산자의 동작 (Java)

분류에서Dev

DNS 확인은 VPN 연결에서 일관성없이 작동합니다.

분류에서Dev

JDK8 및 JDK10에 삼항 연산자의 행동의 차이

분류에서Dev

scanf 단일 문자가 내 루프에서 작동하지 않습니다.

분류에서Dev

자바 스크립트에서 and 연산자의 동작

Related 관련 기사

  1. 1

    ANTLRv4 문법에서 Java 연산자의 연관성 및 우선 순위

  2. 2

    JavaScript의 논리 연산자 및 동작

  3. 3

    이해 '| '및'& '연산자 동작 (R의 논리 연산자)

  4. 4

    파이썬의 ** 연산자 및 * 연산자를 사용하는 동안 서명

  5. 5

    값 내부의 특수 문자는 SQL Server의 = 연산자와 동일하게 작동하는 동안 like 연산자에서 작동하지 않습니다.

  6. 6

    복사 생성자 및 assignemnt 연산자 오버로드가 C ++에서 작동하지 않음

  7. 7

    동일한 테이블에서 N : N 및 1 : N 관계를 생성하는 방법은 무엇입니까?

  8. 8

    && 및 ||를 사용할 수 있습니까? Java의 동일한 if 문에서 연산자?

  9. 9

    Hive에서 여러 개의 동일한 연산자 및 함수 호출을 최적화 하시겠습니까?

  10. 10

    c 프로그래밍에서 논리 및 (&&) 및 논리 또는 (||) 연산자의 혼란스러운 동작

  11. 11

    ## 일명 토큰 붙여 넣기 연산자가 C 및 C ++의 주석에 대해 작동하지 않는 이유는 무엇입니까?

  12. 12

    배열에서 "보다 큼"(및 다른 부등식 비교 연산자)의 동작

  13. 13

    동일한 모델에 대한 Rails 다형성 연관 및 has_many

  14. 14

    생성자 이동 및 할당 이동. 기본 클래스의 연산자

  15. 15

    ">"및 "<"연산자는 문자열 비교에서 어떻게 작동합니까?

  16. 16

    부동 소수점에 관한 연산의 연관성

  17. 17

    C #의 연산자 우선 순위 및 연관성

  18. 18

    생성자 이동 및 클래스에 대한 할당 연산자 이동

  19. 19

    $ set 및 위치 연산자가 Java에서 작동하지 않습니까?

  20. 20

    PHP에서 삼항 및 비교 연산자는 어떻게 작동합니까?

  21. 21

    관계 연산자 요소를 사용하여 numpy 배열의 여러 인덱스에서 작동

  22. 22

    printf-C 언어에서 사용될 때 관계 연산자의 출력 동작

  23. 23

    PHP 임의 연산자 및 작업

  24. 24

    && 및 ||의 혼동 사용 연산자

  25. 25

    접미사 및 접두사 연산자의 동작 (Java)

  26. 26

    DNS 확인은 VPN 연결에서 일관성없이 작동합니다.

  27. 27

    JDK8 및 JDK10에 삼항 연산자의 행동의 차이

  28. 28

    scanf 단일 문자가 내 루프에서 작동하지 않습니다.

  29. 29

    자바 스크립트에서 and 연산자의 동작

뜨겁다태그

보관